0

JFrame に単純なタイム ティッカーを設定しようとしていました。カウンターの初期値を表示できますが、その後の変更は JFrame で更新されません。私が間違っていることへの答えに向けての微調整は大歓迎です。repaint() が呼び出されないのは問題だと思いますが、エラーが発生するか、入れようとしても何もありません。

package com.game.ryan;
import java.awt.Dimension;
import javax.swing.JFrame;
class Screen extends JFrame{


private Dimension d = new Dimension(800,600);
private JFrame f;

public Screen(){
    f = new JFrame();
    f.setIgnoreRepaint(false);
    f.setResizable(false);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setMinimumSize(d);
    f.setLocationRelativeTo(null);
    f.add(new MyPanel());
    f.pack();
    f.setVisible(true);
}

public static void main(String[] args){
    Screen s = new Screen();
}

}

私も持っています:

package com.game.ryan;

import java.awt.Graphics;

import javax.swing.JPanel;

public class MyPanel extends JPanel{

private OneThread ot = new OneThread();
private int counter = ot.getThreadCounter();

public MyPanel(){
    Thread t1 = new Thread(new OneThread());
    t1.start();

}

public void paintComponent(Graphics g){
    g.drawString("TIME: ", 10, 20);
    g.drawString(Integer.toString(counter), 50, 20);        
}
}

そして最後に

package com.game.ryan;

public class OneThread implements Runnable{

private int counter = 45;

public OneThread(){

}

@Override
public void run() {

    for(int x = 0; x >= 0; x++){
        try{
            Thread.sleep(1000);
            counter++;
            x++;
            System.out.println(counter);

        }catch(Exception e){
            e.printStackTrace();
        }
    }       
}

public int getThreadCounter(){
    return counter;
}
}

コンソールでカウンターが増えているので、その部分は正しく機能していると思います。

期待される結果は、カウンタが JFrame に正しく表示されることでした (1000 ミリ秒ごとに更新されます)。

4

2 に答える 2

2

設計を再考することをお勧めします。

  • プリミティブ変数は値を保持し、それだけです。プリミティブが保持する値を別の変数に割り当てた場合、後で元の変数を変更しても、他の変数が保持する値には影響しません。たとえば、JPanel が保持するカウンター変数が保持する値を変更するコードはありません。
  • 計画が成功したとしても、2 つの完全に独立した OneThread オブジェクトがあり、一方の状態を変更しても他方には影響しないことに注意してください。
  • GUI で変数の変更をリッスンし、スレッドで変数の状態を変更してから、すべてのリスナーにこの変更を通知することをお勧めします。これには、PropertyChangeListener がうまく機能します。
  • Swing Timer は、バックグラウンド スレッドよりも実装がはるかに簡単であることに注意してください。
于 2013-05-31T03:01:00.877 に答える
2

UI 自体を更新するように指示する場所はどこにもありません。

また、API 内で既に利用可能なものを複製するためには、はるかに道を踏み外しています。

スイングとスレッドは慎重に検討する必要があります。Swing は、UI のすべての更新を管理するためにシングル スレッド モデルを使用します。UI を使用したすべての反復は、スレッドのコンテキスト内で行われることが期待されます (別名、イベント ディスパッチ スレッド)。

これは、他のスレッドから UI を作成または更新するときはいつでも、EDT への呼び出しを同期する必要があることを意味します。

これを達成する方法はいくつかありますが、あなたの場合、最も簡単なのはjavax.swing.Timer

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LabelClock {

    public static void main(String[] args) {
        new LabelClock();
    }

    protected static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm.ss");
    private JLabel clock;

    public LabelClock() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                clock = new JLabel();
                tick();

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(clock);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Timer timer = new Timer(500, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        tick();
                    }
                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();
            }
        });
    }

    protected void tick() {
        clock.setText(DATE_FORMAT.format(new Date()));
    }

}
于 2013-05-31T03:06:25.627 に答える