java - JProgressBar 绘画问题

标签 java swing jframe jprogressbar event-dispatch-thread

当我设置我的 JProgressBar 的最小值、值和最大值时,它们不会更新,除非我关闭窗口并重新打开它。


图片:

enter image description here

谁能给我一些见解?我在这个问题上挠头。我进行了测试以确保解析正确完成(确实如此)。我测试直接输入数字。显然它有效,它只是在第一次打开窗口时不显示(这让我觉得如果我更新值它只会显示最后的值。

* 编辑 *

女士们先生们……我可以介绍一下……SSCCE。我很抱歉发布这个,因为现在你会感受到我的痛苦 :x


package com.jayavon.game.helper;

import javax.swing.*;
import java.awt.event.*;

public class SSCCE extends JFrame implements WindowListener {

    private static final long serialVersionUID = 1L;
    JFrame frame;
    JPanel panel;
    JButton characterButton;
    JInternalFrame characterFrame;
    /* Character Window */
    JProgressBar totalExpProgressBar;

    Action ClassCharacterButton = new ClassCharacterButton();

    public static void main(String[] args){
        //for thread safety     
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SSCCE();
            }
        });
    }

    SSCCE() {
        initGUI();
    }

    public void initGUI(){

        frame = new JFrame("SSCCE");
        panel = (JPanel)frame.getContentPane();

        /**********************************
         ** 
         **     Buttons
         **    
         *********************************/
        characterButton = new JButton("");
        characterButton.setBounds(50,175,395,100);
        characterButton.setVisible(true);
        characterButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("C"), "characterButtonPress");
        characterButton.getActionMap().put("characterButtonPress", ClassCharacterButton);
        characterButton.setAction(ClassCharacterButton);
        characterButton.setText("Click me three times(open/close/open) to get progress bar to fill");
        panel.add(characterButton);

        /**********************************
         ** 
         **     Internal Frames
         **    
         *********************************/
        //#### Character frame start ####
        characterFrame = new JInternalFrame("Character", true, true, false, false);
        characterFrame.setLocation(50, 50);
        characterFrame.setSize(300,105);

        totalExpProgressBar = new JProgressBar();
        totalExpProgressBar.setString("0/0");
        totalExpProgressBar.setStringPainted(true);

        characterFrame.add(totalExpProgressBar);
        characterFrame.setResizable(false);
        panel.add(characterFrame);
        //#### Character frame end ####

        /**********************************
         ** 
         **     Panel Code
         **    
         *********************************/
        panel.setLayout(null);
        panel.setFocusable(true);

        /**********************************
         ** 
         **     Frame Code
         **    
         *********************************/
        frame.setLocation(100, 100);
        frame.setSize(500, 350);
        frame.setVisible(true);
        frame.setFocusable(true);
        frame.addWindowListener(this);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    class ClassCharacterButton extends AbstractAction {  
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            if (characterFrame.isVisible()){
                characterFrame.setVisible(false);
            } else {
                fakeGetServerResponse();
            }
        }
    }

    public void fakeGetServerResponse(){
        String incommingReply = "proskier-charactersWindow@20|10|10|10|0|234|3|200|400"; //fake message from server
        final String splitAt[] = incommingReply.split("@"); //split the character name from the incommingReply at the '@' sign
        String beforeAt[] = splitAt[0].split("-");
        String commandName = beforeAt[1];
        final String afterAt[] = splitAt[1].split("\\|");

        if (commandName.equals("charactersWindow")){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    totalExpProgressBar.setString(afterAt[5] + "/" + afterAt[8]);
                    totalExpProgressBar.setMinimum(0);
                    totalExpProgressBar.setMinimum(Integer.parseInt(afterAt[7])); //TODO::SCREW YOU JAVA
                    totalExpProgressBar.setValue(Integer.parseInt(afterAt[5]));   //TODO::SCREW YOU JAVA
                    totalExpProgressBar.setMaximum(Integer.parseInt(afterAt[8])); //TODO::SCREW YOU JAVA
                    characterFrame.setVisible(true);
                }
            });
        }
    }

    @Override
    public void windowClosing(WindowEvent arg0){
        frame.dispose();
        System.exit(1);
    }
    @Override
    public void windowActivated(WindowEvent arg0) {
    }
    @Override
    public void windowClosed(WindowEvent arg0) {
    }
    @Override
    public void windowDeactivated(WindowEvent arg0) {
    }
    @Override
    public void windowDeiconified(WindowEvent arg0) {           
    }
    @Override
    public void windowIconified(WindowEvent arg0) {
    }
    @Override
    public void windowOpened(WindowEvent arg0) {            
    }
}

最佳答案

您可能正在 EDT(事件调度线程)中执行工作。这个线程有一个事件队列,它们一次按顺序分派(dispatch)一个,因为 AWT 不是线程安全的。这允许 UI 更新和响应事件(重新绘制或 invokeLater 等编程事件,或鼠标和按键事件等用户事件)。

因此,当您在 EDT 中工作时,您会阻塞线程并阻止其调度事件,例如重绘、点击、按键事件等...

通常解决方案是将工作转移到另一个线程中,例如使用 SwingWorker .

顺便说一句,Thread.sleep(long) 是一个静态方法,因此无需调用 currentThread(),如果需要,只需调用 Thread.sleep(...) 即可。但同样,您真的应该避免在 EDT 中这样做,因为它会阻止它并且还会阻止 UI。

关于java - JProgressBar 绘画问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10342309/

相关文章:

java - AWT 滚动 Pane 滚动条在调整大小时闪烁

java - 两个类之间如何发生碰撞和 react ?

java - 存储 Clojure(或 JVM)应用程序使用的文件的常规位置

java - 通过按钮使imageView可见和不可见

java - jsp/servlets 从数组中填充下拉框

java - 未显示 JFrame 的内容

Java - 如何使用鼠标监听器突出显示方 block 。 (使用jframe)

java - 将数据数组保存到数据库

java - 我的 JPanel 中的 .showMessageDialog 出现错误?

java - JFrame 在 TextPane 设置之前退出