Java ScrollPane (with a TextArea inside) can not scroll to top programmatically - java

To abstract this problem, I put 2 buttons. One is called "Add & toTop", another is called "toTop"
And there is no text in the textArea at the very beginning.
And I add the actionListener for "Add & toTop" button like this:
btn1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
textArea1.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
+ "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
//A long enough String
JScrollBar jb = scrollPane1.getVerticalScrollBar();
jb.setValue(jb.getMinimum());
scrollPane1.repaint();
}
});
So the function of the first button is :"Add some text and Scroll to Top"
But it will only add text but will not scroll to top
However for the second button, I add a actionListener like this:
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JScrollBar VerticalScrollBar = scrollPane1.getVerticalScrollBar();
VerticalScrollBar.setValue(VerticalScrollBar.getMinimum());
scrollPane1.repaint();
}
});
So, I press the second button after pressing the first button, the second button will perform well.
And I really feel confused that why the first button will not scroll to top :<

A simple solution might be to use JTextArea#setCaretPosition, for example
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea ta;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(5, 20);
add(new JScrollPane(ta));
JButton btn = new JButton("Add and to top");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ta.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
+ "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
ta.setCaretPosition(0);
}
});
add(btn, BorderLayout.SOUTH);
}
}
}
I had a play around with scrollRectToVisible, but ended up having to use SwingUtilites.invokeLater to make it work, for example...
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ta.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
}
});
so I'd say setCaretPosition in this case is the simpler solution

Related

How to make a border around Jbutton thicker?

I have the following JButton on the GUI interface I'm building.
I want to make the border around the button more thicker so it will stand out from the background. Is it possible to do this in Java?
You could simply use a LineBorder
JButton btn = ...;
btn.setBorder(BorderFactory.createLineBorder(Color.BLACK, 4));
Take a look at How to Use Borders for more details and ideas
Updating the border state based on the model state
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final Border NORMAL_BORDER = BorderFactory.createLineBorder(Color.BLACK, 4);
protected static final Border ROLLOVER_BORDER = BorderFactory.createLineBorder(Color.RED, 4);
public TestPane() {
JButton btn = new JButton("Click me!");
btn.setContentAreaFilled(false);
btn.setBorder(NORMAL_BORDER);
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (btn.getModel().isRollover()) {
btn.setBorder(ROLLOVER_BORDER);
} else {
btn.setBorder(NORMAL_BORDER);
}
}
});
setLayout(new GridBagLayout());
add(btn);
}
}
}
Create a Border first -
Border border = new LineBorder(Color.WHITE, 13);
Then create a JButton and set the Border -
JButton button = new JButton("Button Name");
button.setBorder(border);
Hope it will Help.
Thanks a lot.

Right click on JButton to lock it and change its colour Java

I am a beginner at java so am attempting to create a minesweeper game. I have a grid full of JButtons that when clicked reveal numbers or mines.
I want to add "flags" so when I right click on any button it changes colour - showing it has been flagged and is 'locked' so it cannot be clicked on unless right clicked.
Here are my buttons
public void buttons()
{
// Creating the grid with buttons
grid.setLayout(new GridLayout(20,20));
// Button grid
for (int x = 0; x < buttons.length; x++)
{
for (int y = 0; y < buttons.length; y++)
{
buttons[x][y] = new JButton();
buttons[x][y].addActionListener(this);
grid.add(buttons[x][y]);
}
}
I attempted to create this right click functionality but I am currently stuck and would like some help.
public void flag()
{
buttons.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
JButton rightClick = new JButton("Right Click");
rightClick.addActionListener(this);
}
});
}
Typically, you would process user events on a button via the button's ActionListener, what you want to try and do is stop the user from trigger the buttons ActionListener, the easiest way that you can do this is disable the button...
Normally, I don't like using MouseListeners on buttons as this is not normally the best way to ascertain user interaction, but in this case, it's the requirement
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JButton btn;
public TestPane() {
setBorder(new EmptyBorder(8, 8, 8, 8));
setLayout(new GridBagLayout());
btn = new JButton("O");
btn.setMargin(new Insets(8, 8, 8, 8));
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("You clicked me");
}
});
btn.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
btn.setEnabled(!btn.isEnabled());
if (btn.isEnabled()) {
btn.setText("O");
} else {
btn.setText("X");
}
}
}
});
}
}
}

Dynamic JLable Text

I'm a super Java noob and need some help. I am trying to write a code that shows the word "on" on the JPanel for 5 (or however long I pass into y variable) seconds then changes the word to "off" on the same JPanel. Think of a stoplight that shows green for a period of time then goes to red. The code I have written below opens up two separate JFrames to display the different words. Any help or ideas would be greatly appreciated.
import javax.swing.*;
public class practice extends JFrame implements Runnable {
int x;
int y;
JLabel show = new JLabel("on");
JLabel show2 = new JLabel("off");
boolean yes;
public practice(boolean on, int x){
x=y;
yes = on;
setTitle("Stoplight");
setSize(500, 500);
setResizable(true);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void test(){
try {
Thread.sleep(y);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (yes == true){
add(show2);
}else if (yes == false)
add(show);
}
public void run() {
test();
}
public static void main (String[] args){
Thread t1 = new Thread(new practice(true, 50000));
Thread t2 = new Thread(new practice(false, 0));
t1.start();
t2.start();
}
}
You need remove the label 'on' of panel before add the label 'off' with the method remove(jcomponent)
As has already been hinted, you should use a javax.swing.Timer, which will allow you to schedule a callback after a specified period of time.
Unless you have a particular need, it's simpler to change the text of the label to have to remove the old label and add a new one (IMHO)
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class DynamicLabel {
public static void main(String[] args) {
new DynamicLabel();
}
public DynamicLabel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane(5000));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
public TestPane(int delay) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(8, 8, 8, 8));
label = new JLabel("On");
add(label);
Timer timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText("Off");
}
});
timer.setRepeats(false);
timer.start();
}
}
}

How to work with JButton?

Hi I am trying to make java desk top application where I am using 3 JButtons. I want that when I click any JButton it should change the color of that button and if I click on any other JButton then previous clicked button should be like before and recently clicked button change its color until another JButton is clicked
How can I achieve this
here is my button code
b1 = new JButton("Ok");
b1.setBounds(800, 725, 100, 40);
b1.setForeground(Color.BLACK);
c.add(b1);
b2 = new JButton("Print");
b2.setBounds(925, 725, 100, 40);
b2.setForeground(Color.BLACK);
c.add(b2);
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
b1.setBackground(Color.BLUE);
JOptionPane.showMessageDialog(frame,"Welcome to allhabad High Court");
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
b2.setBackground(Color.BLUE);
JOptionPane.showMessageDialog(frame,"Welcome to allhabad High Court");
}
});
This is actually more tricky then it sounds. Some look and feels don't use the background color property when rendering the buttons (for example Windows)
A possible solution might be to use a ButtonGroup and JToggleButton, which will ensure that only one button is selected at a time and allow you to monitor the selected states of the buttons, for example...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ToggleButton {
public static void main(String[] args) {
new ToggleButton();
}
public ToggleButton() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final JToggleButton b1 = new JToggleButton("Ok");
b1.setContentAreaFilled(false);
b1.setOpaque(true);
b1.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (b1.isSelected()) {
b1.setBackground(Color.BLACK);
} else {
b1.setBackground(null);
}
}
});
final JToggleButton b2 = new JToggleButton("Print");
b2.setContentAreaFilled(false);
b2.setOpaque(true);
b2.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (b2.isSelected()) {
b2.setBackground(Color.BLUE);
} else {
b2.setBackground(null);
}
}
});
ButtonGroup bg = new ButtonGroup();
bg.add(b1);
bg.add(b2);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(b1);
frame.add(b2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Another solution might be to use JRadioButton instead, which is generally used to indicate a single selection from a group of options.
See How to Use Buttons, Check Boxes, and Radio Buttons
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
b1.setBackground(Color.BLUE);
b2.setBackground(Color.BLACK);
JOptionPane.showMessageDialog(frame,"Welcome to allhabad High Court");
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
b2.setBackground(Color.BLUE);
b1.setBackground(Color.BLACK);
JOptionPane.showMessageDialog(frame,"Welcome to allhabad High Court");
}
});

stopCellEditing on JDialog

My question is similar to this one: JTable Cell Update doesn't work.
However, I am using JDialog instead of a JTable specified in above link. I have a custom class which extends JDialog. I use JEditorPane as a text-component in that dialog and create simple OK, Cancel buttons. Now the problem is, when I enter something in the JEdiorPane and presses OK button, the value is not applied to the text-component until I move the focus out of a JDialog or hit tab/ENTER.
I want the container to be notified that I am done with editing as soon as I press the OK button. In short I want to explicitly have a feature similar to stopCellEditing(). How can I do that?
See this example which seems to work correctly and does the same thing as you described:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TestEditorPaneDialog {
public void init() {
final JFrame frame = new JFrame();
JButton clickMe = new JButton("Click me");
clickMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showDialog(frame);
}
});
frame.add(clickMe);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
showDialog(frame);
}
private void showDialog(final JFrame frame) {
final JDialog dialog = new JDialog(frame, true);
final JEditorPane pane = new JEditorPane();
pane.setText("Type something here");
JPanel south = new JPanel();
JPanel buttons = new JPanel(new GridLayout(1, 0, 10, 10));
JButton ok = new JButton("OK");
ok.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
JOptionPane.showMessageDialog(frame, "You have typed in: " + pane.getText());
}
});
JButton cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
buttons.add(ok);
buttons.add(cancel);
south.add(buttons);
dialog.add(new JScrollPane(pane));
dialog.add(south, BorderLayout.SOUTH);
dialog.setSize(250, 150);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestEditorPaneDialog().init();
}
});
}
}

Categories