[JAVA] When I tried to scroll automatically with JScrollBar, the event handler was drawn only once.

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.

What was made

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 ...

What went wrong

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.

Solution

(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

Summary

  1. Don't try to do anything with an event handler
  2. In the event handler, the drawing process is basically performed only once at the end.
  3. Use invokeLater () if you want to do some drawing processing from other than the event handler thread in Swing.

Digression

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());
}

that's all.

Recommended Posts

When I tried to scroll automatically with JScrollBar, the event handler was drawn only once.
Problems I was addicted to when building the digdag environment with docker
I tried to summarize the points to consider when acquiring location information with the iOS application ③
I tried to summarize the points to consider when acquiring location information with the iOS application ①
When I tried to unit test with IntelliJ, I was told "java.lang.OutOfMemoryError: Java heap space"
I tried to summarize the points to consider when acquiring location information with the iOS application ②
A story I was addicted to when getting a key that was automatically tried on MyBatis
What I was addicted to when introducing the JNI library
I tried to increase the processing speed with spiritual engineering
What I was addicted to with the Redmine REST API
When I tried to run Azure Kinect DK with Docker, it was blocked by EULA
I tried upgrading from CentOS 6.5 to CentOS 7 with the upgrade tool
The story I was addicted to when setting up STS
I tried to solve the problem of "multi-stage selection" with Ruby
I tried to build the environment of PlantUML Server with Docker
I tried to implement the image preview function with Rails / jQuery
I tried to translate the error message when executing Eclipse (Java)
What I was addicted to when implementing google authentication with rails
I checked because the response was strange when debugging with Tomcat 8
I tried to check the operation of gRPC server with grpcurl
Automatically scroll the background with libGDX
I tried to interact with Java
I tried to explain the method
I tried to figure out the flow when performing image analysis with Vision Framework and Core ML
[Rails] I was addicted to the nginx settings when using Action Cable.
I tried to summarize the stumbling points when developing an Android application
A story I was addicted to when testing the API using MockMVC
[Ruby] I tried to diet the if statement code with the ternary operator
I tried to solve the tribonacci sequence problem in Ruby, with recursion.
I tried to visualize the access of Lambda → Athena with AWS X-Ray
I was addicted to unit testing with the buffer operator in RxJava
I was stuck with the handling of the time zone when formatting with SimpleDateFormat
I tried to measure and compare the speed of GraalVM with JMH
When I try to sign up with devise, it automatically redirects to root_path
I tried to summarize the methods used
Since the du command used when the capacity is full is difficult to use, I tried wrapping it with ruby
I tried to get started with WebAssembly
I was addicted to the roll method
I tried to implement the Iterator pattern
I was addicted to the Spring-Batch test
I tried to summarize the Stream API
I tried to implement ModanShogi with Kinx
What I tried when I wanted to get all the fields of a bean
I tried to compare the infrastructure technology of engineers these days with cooking.
I tried to get the distance from the address string to the nearest station with ruby
I tried to summarize again the devise that was difficult at first sight
[JavaScript] The strongest case when I tried to summarize the parts I do not understand
I tried to automatically generate a class to convert from a data class to a Bundle with APT
When I tried to use a Wacom tablet with ubuntu 20.04, I didn't recognize it.
I tried to verify AdoptOpenJDK 11 (11.0.2) with Docker image
I tried to make Basic authentication with Java
I tried to manage struts configuration with Coggle
[Rails] I tried to raise the Rails version from 5.0 to 5.2
I tried to organize the session in Rails
I was addicted to doing onActivityResult () with DialogFragment
I tried to set tomcat to run the Servlet.
I tried to break a block with java (1)
What I was addicted to when developing a Spring Boot application with VS Code
A memo that I was addicted to when making batch processing with Spring Boot
When creating the top page, I was stuck with the handling of images (super beginner)
[Beginner's point of view] I tried to solve the FizzBuzz problem "easily" with Ruby!