Event of scroll bar in JTextArea - java

I have a text area, whenever the scroll bar is scrolled, I want to call a method. On what event I should call the method? I tried:
private void jScrollPane1MouseReleased(java.awt.event.MouseEvent evt) {
//execute();
System.out.println("Scroller Moved");
}

You want to use the AdjustmentListener on the JScrollBar (choose the one you want to listen for movement on). Here's an example of listening on the vertical bar.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TempProject extends JPanel{
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 2000));
JScrollPane pane = new JScrollPane(panel);
pane.setPreferredSize(new Dimension(400, 300));
pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener(){
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println("Hi Mom!");
}});
frame.setContentPane(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

You should use a mouselistener event instead.
If you'd like to know more about it check it out here - http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html

use the mouseclicked method then get the coordinates using getX() and getY(), then with an if test, test to see whether the coordinates are within the dimensions of your JScrollPane. Just remember to implement mouselister and add all inherited abstract methods :)

Related

Is it a bad idea to call pack() in JFrame.invalidate?

I've built a simple gui that adds panels based on user input. My initial problem was that when the panel was added the frame did not resize. Because it was a jpanel object that handled the user input adding a new panel to itself and therefore could not 'see' the jframe (at least I couldn't find how it could) I couldn't work out how to call repaint() or revalidate() on the parent frame from within that object. However,through trial and error I did find that this worked
JFrame jFrame = new JFrame(title){
#Override
public void invalidate(
super.invalidate();
this.pack();
}
};
But because I don't really know what goes on behind the scenes with invalidate I want to know whether this is a good idea or not (It seems kinda sketchy). Any advice would be great, thanks.
EDIT
Hope this makes the problem a bit clearer
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class TestFrame {
JFrame jframe;
NewPanel jpanel;
public TestFrame(){
jframe = new JFrame(); // without above addition frame won't resize
jpanel = new NewPanel();
jframe.add(jPanel);
jframe.pack();
jframe.setVisible(true);
}
public static void main(String [] args){
TestFrame testframe= new TestFrame();
}
}
class NewPanel extends JPanel implements ActionListener{
public NewPanel(){
JTextField textField = new JTextField (10);
textField.addActionListener(this);
this.add(textField);
}
// Adds a label when action is performed on textfield
#Overide
public void actionPerformed(ActionEvent ae){
JPanel extraPanel = new JPanel();
extraPanel.add(new JLabel("hi"));
this.add(extraPanel);
this.revalidate(); this.repaint();
}
}
Your issue is not that revalidate() or repaint() aren't working.
The issue here is that your JFrame has been pack()ed already and thus it has a preferred size set. If you want to change its size you need to call pack() on it again. Not necessarily to call it on invalidate().
I made some changes to your code to compile (typos) and I came with this:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestFrame {
JFrame jframe;
NewPanel jpanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TestFrame());
}
public TestFrame(){
jframe = new JFrame(); // without above addition frame won't resize
jpanel = new NewPanel();
jframe.add(jpanel);
jframe.pack();
jframe.setVisible(true);
}
class NewPanel extends JPanel implements ActionListener{
public NewPanel(){
JTextField textField = new JTextField (10);
textField.addActionListener(this);
this.add(textField);
}
// Adds a label when action is performed on textfield
#Override
public void actionPerformed(ActionEvent ae){
System.out.println("WOLOLO");
JPanel extraPanel = new JPanel();
extraPanel.add(new JLabel("hi"));
this.add(extraPanel);
this.revalidate();
this.repaint();
jframe.pack();
}
}
}
Another way to solve this is to override getPreferredSize method from the JPanel:
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
And you can delete jframe.pack() in the previous code.

Java JButton - making simple menu

Hi take a look on this code:
package arkanoid;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.event.*;
public class Arkanoid extends JFrame
{
private static final long serialVersionUID = 6253310598075887445L;
static JFrame frame;
static class Action1 implements ActionListener {
public void actionPerformed (ActionEvent e) {
//frame = new JFrame("Arkanoid");
frame.setLocationRelativeTo(null);
frame.setIgnoreRepaint(true);
frame.setResizable(false);
frame.setVisible(true);
frame.setSize(500,400);
frame.add(new Gra());
}
}
static class Action2 implements ActionListener {
public void actionPerformed (ActionEvent e) {
frame.dispose();
System.exit(0);
}
}
public static void main(String[] args)
{
//new Arkanoid();
frame = new JFrame("Arkanoid");
frame.setSize(500,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Arkanoid BETA");
frame.setLocationRelativeTo(null);
frame.setIgnoreRepaint(true);
frame.setResizable(false);
frame.setVisible(true);
JPanel panel = new JPanel();
frame.add(panel);
JButton button = new JButton("Nowa Gra");
panel.add(button);
button.addActionListener (new Action1());
JButton button2 = new JButton("Wyjscie");
panel.add(button2);
button2.addActionListener (new Action2());
}
}
This code almost works, I want to make a button2 a quit button working like X button in top right frame's icons and button1 need to open a Gra() in the same window. When im doing it like this it isnt work fine:/ i need to click 2 times on button1 to go to Gra() and what is more KeyListeners in Gra() arent working :(
Im new in buttons, frames and panels in java so please help with this code. Correct it please.
There are a number of fundamental problems with your code, the least of which is why your button1 requires 2 clicks.
However, for your problem you should try rearranging the order of your button1 listener, so that your Component is added to the frame first, before setting it to be visible. An example that should work:
static class Action1 implements ActionListener {
public void actionPerformed (ActionEvent e) {
frame.add(new Gra());
frame.revalidate();
}
}
Note you have already set the size, location etc of frame in main, so there is no need to set them again every time the button is clicked.
I stress that there are more important problems with your code than this issue. You should take a look at Java's Modifier Types (static does not seem applicable here), as well as object-oriented concepts such as inheritance (you define your Arkanoid class to extend JFrame, yet have a JFrame object as a class variable).
I want to make a button2 a quit button working like X button in top right frame's
You can use the ExitAction class found in Closing an Application.
For other examples of how to use buttons read the Swing tutorial on How to Use Buttons. This is the place to start for all you Swing related questions.
There are many problems with your code. I've refactored it a little. With below code & #ricky116 answer I think you should get all of them.
import javax.swing.*;
import java.awt.Color;
import java.awt.event.*;
public class Arkanoid extends JFrame
{
public Arkanoid() {
super("Arkanoid");
setSize(500,400);
setTitle("Arkanoid BETA");
setLocationRelativeTo(null);
setResizable(false);
final JPanel panel = new JPanel();
setContentPane(panel);
panel.add(new JButton(new AbstractAction("Nowa Gra") {
public void actionPerformed (ActionEvent e) {
panel.removeAll();
panel.add(new Gra());
panel.revalidate();
panel.repaint();
}
});
panel.add(new JButton(new AbstractAction("Wyjscie") {
public void actionPerformed (ActionEvent e) {
Arkanoid.this.setVisible(false);
}
});
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Arkanoid frame = new Arkanoid();
frame.setVisible(true);
}
});
}
}

JButton and JLabel dissappears when adding custom background

JButton and JLabel disappears when adding custom background. I don't see any problems in my program, but maybe you guys find an solution! I think it's only a little thing I forgot, but I can't figure it out.
Here's the code:
GameWindow.java:
setContentPane(new StartImagePanel(RollrackLogo));
out.println("adding JLWelcome");
JLWelcome.setText("Welcome to Rollrack, " + namewindow.name);
add(JLWelcome);
JLWelcome.setVisible(true);
out.println("JLWelcome added");
out.println("adding JBRandom");
JBRandom.setText("Random");
add(JBRandom);
JBRandom.setVisible(true);
out.println("added JBRandom");
The background appears perfect, but not the JButton and JLabel!
Code to the StartImagePanel.java:
public class StartImagePanel extends JComponent{
private Image image;
public StartImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
Your button and label are added to your GameWindow frame while they should be added to its contentPane, setContentPane(new StartImagePanel(RollrackLogo)); instead. That's why they are not showing, they are added to the frame.
Make a variable of the StartImagePanel and add the button and label to it and they should show up.
StartImagePanel contentPanel = new StartImagePanel(RollrackLogo);
setContentPane(contentPanel);
...
out.println("adding JLWelcome");
JLWelcome.setText("Welcome to Rollrack, " + namewindow.name);
contentPanel.add(JLWelcome);
JLWelcome.setVisible(true);
out.println("JLWelcome added");
out.println("adding JBRandom");
JBRandom.setText("Random");
contentPanel.add(JBRandom);
JBRandom.setVisible(true);
out.println("added JBRandom");
Answer dispute
The claims in the first paragraph are plain wrong. Here is source that proves it.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class AddToCustomContentPane {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
// the GUI as seen by the user (without frame)
JPanel gui = new JPanel(new FlowLayout());
gui.setBorder(new EmptyBorder(2, 3, 2, 3));
gui.setBackground(Color.RED);
JFrame f = new JFrame("Demo");
f.setContentPane(gui);
// Acid test. Can we add buttons direct to the frame?
f.add(new JButton("Button 1"));
f.add(new JButton("Button 2"));
// Ensures JVM closes after frame(s) closed and
// all non-daemon threads are finished
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See http://stackoverflow.com/a/7143398/418556 for demo.
f.setLocationByPlatform(true);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
Edit after the custom panel code was given
Here's a snippet that works to show both button and label on a black image background, I removed that was not needed (listeners).
public static void main(String[] v) {
class StartImagePanel extends JPanel {
private Image image;
public StartImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
class GameWindow extends JFrame{
public GameWindow() {
BufferedImage RollrackLogo;
RollrackLogo = new BufferedImage(400,200,BufferedImage.TYPE_INT_RGB);
final JButton JBRandom = new JButton();
final JLabel JLWelcome = new JLabel();
setDefaultCloseOperation(EXIT_ON_CLOSE);
StartImagePanel panel = new StartImagePanel(RollrackLogo);
setContentPane(panel);
setExtendedState(MAXIMIZED_BOTH);
setVisible(true);
JLWelcome.setText("Welcome to Rollrack");
panel.add(JLWelcome);
JLWelcome.setVisible(true);
JBRandom.setText("Random");
panel.add(JBRandom);
JBRandom.setVisible(true);
}
}
GameWindow window = new GameWindow();
window.pack();
window.setVisible(true);
}
I rather use an instance of a JFrame, instead of extending it, as #Andrew Thompson suggested in another question.
However, if you're extending it, it might be a good practice to call super() in the constructor.
Additionally, we may need to know what is going on in your StartImagePanel.
It seems, to me, to be the problem.
Ensure both your GameWindow and StartImagePanel extend properly their superclasses (call super();).
Ensure your StartImagePanel has a proper Layout.
Add your components before you set your frame visible. This also means you won't need JLWelcome.setVisible(true);.
Ensure that your code is executed in the EDT (Event-Dispatch Thread).
Example:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameWindow extends JFrame{
BufferedImage rollrackLogo;
JButton jbRandom;
JLabel jlWelcome;
public GameWindow() {
super();
jbRandom = new JButton("Random");
jlWelcome = new JLabel("Welcome to Rollrack, " +
namewindow.name);
rollrackLogo = new BufferedImage(400, 200,
BufferedImage.TYPE_INT_RGB);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setContentPane(new StartImagePanel(rollrackLogo));
// Add your components.
add(jlWelcome);
add(jbRandom);
addKeyListener(new KeyListener() {
#SuppressWarnings("static-access")
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == e.VK_ESCAPE){
System.exit(7);
}
}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
});
// Pack, or otherwise set fullscreen.
pack();
// Now, set frame visible.
setVisible(true);
}
}
Edit: Now that you've posted the code for your StartImagePanel, I see that you're extending JComponent. Follow my previous advice, (call super), set a Layout, and extend JPanel instead.

What is the difference: getValueIsAdjusting() in both JScrollBar and AdjustmentEvent? + How to listen to the buttons of JScrollBar?

They are actually two questions:
The First question:
What is the difference between getValueIsAdjusting() in both JScrollBar and of AdjustmentEvent
I tried them with some code to test if any difference, but I didn't get any!. Here is the code to show How I tested them.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ScrollTest extends JPanel
{
JPanel panel;
JScrollBar scroll;
public ScrollTest()
{
scroll = new JScrollBar(JScrollBar.HORIZONTAL, 0, 6, 0, 300);
scroll.addAdjustmentListener(ScrollListener);
panel = new JPanel(new GridLayout(1, 0));
panel.add(scroll);
this.setLayout(new BorderLayout());
this.add(panel);
}
AdjustmentListener ScrollListener = new AdjustmentListener()
{
#Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
if(e.getValueIsAdjusting())
{
System.out.println("AdjustmentEvent");
}
if(scroll.getValueIsAdjusting())
{
System.out.println("JScrollBar");
}
}
};
private static void createAndShowGUI()
{
JFrame frame;
frame = new JFrame("Scroll Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(880, 100);
frame.add(new ScrollTest(), BorderLayout.CENTER);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
The code above will print "AdjustmentEvent" and "JScrollBar" strings in sequence. it seems there is no difference between them!
The important point is when/for what to use each?
The Second question:
How to listen to JScrollBar buttons? if you tested the above code, it prints the strings when you move the knob or click on the strip, but not when you click the buttons of the JScrollBar!
Add one more event (as stated here) in the adjustmentValueChanged of AdjustmentListener class.
If event type is AdjustmentEvent.TRACK then also print a statement.
if(e.getValueIsAdjusting())
{
System.out.println("AdjustmentEvent");
}
if(scroll.getValueIsAdjusting())
{
System.out.println("JScrollBar");
}
if(e.getAdjustmentType() == AdjustmentEvent.TRACK)
{
System.out.println("The button in scrollbar clicked");
}
This will capture the button click action on the JScrollBar.

Why does my JFrame stay empty, if I subclass JPanel and JFrame?

I'm trying to write custom JFrame and JPanel for my Java application. Currently, I just want to have a JPanel with a start button in the very middle of the screen. So, here's the code I have:
package gui;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class SubitizingFrame extends JFrame implements KeyListener {
public SubitizingFrame() {
super("Subitizing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
add(new LaunchPanel());
pack();
setVisible(true);
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_F5)
System.out.println("F5 pressed");
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
and here is my panel:
package gui;
import instructions.Settings;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class LaunchPanel extends JPanel implements ActionListener {
private JButton startButton;
public LaunchPanel() {
int width = Settings.getScreenSizeX(), height = Settings.getScreenSizeY();
setPreferredSize(new Dimension(width, height));
setLayout(null);
startButton = new JButton("Start");
startButton.setLocation((width/2) - (startButton.getWidth()/2), (height/2) - (startButton.getHeight()/2));
add(startButton);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
But when the application launches, I don't see anything. Just a big gray screen.
Do not use a null layout. If you simply use the default layout manager of JPanel (i.e. FlowLayout), the JButton with "automagically" be placed in the center. Also, in order to place the JFrame in the middle of the screen, invoke setLocationRelativeTo(null).
Since it's hard to tell what you mean by "screen", this example shows how you center a JButton in a JPanel in a JFrame, that is then centered on the monitor.
public final class CenterComponentsDemo {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame("Center Components Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonPane());
frame.setSize(new Dimension(300, 100)); // Done for demo
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class ButtonPane extends JPanel{
public ButtonPane(){
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBackground(Color.PINK);
final JButton button = new JButton("Start");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
add(Box.createVerticalGlue());
add(button);
add(Box.createVerticalGlue());
}
}
}
Recommendations:
Avoid using null layout as this makes your app difficult to upgrade and maintain and makes it potentially very ugly or even non-usable on boxes with different OS's or screen resolutions.
If you have your JPanel use a GridBagLayout and add a single component to it without using GridBagConstraints, it will be placed in the center of the JPanel.
You almost never have to or should extend JFrame and only infrequently need to extend JPanel. Usually it's better to enhance your GUI classes through composition rather than inheritance.
Avoid having your "view" or gui classes implement your listener interfaces. This is OK for "toy" programs, but as soon as your application gains any appreciable size or complexity, this gets hard to maintain.
If you don't use any LayoutManager (which btw you probably should), then you'll need to set the size of the panel as well (along with its position).
Although we strongly recommend that you use layout managers, you can perform layout without them. By setting a container's layout property to null, you make the container use no layout manager. With this strategy, called absolute positioning, you must specify the size and position of every component within that container. One drawback of absolute positioning is that it does not adjust well when the top-level container is resized. It also does not adjust well to differences between users and systems, such as different font sizes and locales.
From: http://download.oracle.com/javase/tutorial/uiswing/layout/using.html
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class LaunchPanel extends JPanel {
private JButton startButton;
public LaunchPanel() {
int width = 200, height = 100;
setPreferredSize(new Dimension(width, height));
setLayout(new GridBagLayout());
startButton = new JButton("Start");
add(startButton);
setBorder( new LineBorder(Color.RED, 2));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, new LaunchPanel());
}
});
}
}
addKeyListener(this);
Don't use KeyListeners. Swing was designed to be used with Key Bindings. Read the section from the Swing tutorial on How to Use Key Bindings for more information.
The tutorial also has a section on Using Layout Manager which you should read. You should not create GUI's with a null layout.

Categories

Resources