It got stuck and was blown away for a few hours, so instead of a memo. Anyone who uses Swing seems to have failed once.
I was trying to make something like a self-made shell in Java, and I was trying to make JScrollPane scroll automatically. This is the source code I wrote while checking.
MyShell.java
class MyShell extends JFrame implements ActionListener{
MyShell{
//(Omitted)
String now = new File(".").getAbsoluteFile().getParent().toLowerCase();//Current directory
JTextField text = new JTextField();//Input area
text.addActionListener( this );
JTextArea area = new JTextArea(now+"->");//Display area
JScrollPane scrollpane = new JScrollPane(area);
JPanel p = new JPanel()
p.add(text,BorderLayout.SOUTH);
p.add(scrollpane);
//(Omitted)
}
public void actionPerformed(ActionEvent e){
String input = text.getText().toLowerCase();
if(input.equals("exit")){System.exit(0);}//For forced termination
area.append(text.getText()+"\nPC->"+mani(input.split(" "))+"\n\n"+now+"->");//Added to the drawing area
text.setText("");//Erase the contents of the input area
JScrollBar scrollBar = scrollpane.getVerticalScrollBar();
scrollBar.setValue(scrollBar.getMaximum());
}
public String mani(String[] input){
//Command interpretation function
}
//(Omitted)
}
For the time being, actionPerformed is called when the enter key is pressed in the input text field (reference link) ). Then, immediately after pressing the enter key, the command is interpreted and added to the drawing area. After that, it was scrolled by the height of the scroll bar, and the bottom of the JTextArea was displayed ...
In conclusion, the process registered as an event handler is drawn after all the processes are completed. In other words, the size that can be obtained with `scrollBar.getMaximum ()`
is the size before redrawing, so you can only go to the bottom of the JTextArea before redrawing. If you try inserting Thread.sleep (1000)
in the last line of ʻactionPerformed`, you can see the behavior well.
Well, if you think about it carefully, it's better to do the drawing process as few times as possible, and of course it's natural.
(If you search the net properly, you can get as much information as you want ...)
Think of a single event handler as allowing only state changes and a single repaint call. Even if you call repaint multiple times, the paintComponent method will only be called once. Source: https://teratail.com/questions/75183
Upon further investigation, this article is ... Some people were stuck with the same thing ... I put the code in this article into ʻaction Performed` and it worked fine.
Swing also seemed to be a single thread design.
The invokeLater () method ... fires after all pending AWT events have been processed
Source: http://wisdom.sakura.ne.jp/system/java/swing/swing4.html
As an aside, I also tried using paintImmediately
. Apparently, only the drawing process is used, and other numerical values are updated after the event handler ends.
MyShell.java
actionPerformed(ActionEvent e){
System.out.println(scrollbar.getValue()+"#"+scrollbar.getMaximum()+"#"+area.getHeight());
p.paintImmediately(0,0,5000,5000);
System.out.println(scrollbar.getValue()+"#"+scrollbar.getMaximum()+"#"+area.getHeight());
}
Recommended Posts