0

これは、JComponentsを描画する必要があるフォームの関連コードです。このコードは、後でコンポーネントを破棄できるようにする必要があるため、JComponentを作成してフォームに追加し、ArrayListにも追加します。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JOptionPane;

public class frmMain extends javax.swing.JFrame implements ActionListener {
  ArrayList<Pocitadlo> poc;
  Random rnd;
  /**
   * Creates new form frmMain
   */
  public frmMain() {
    initComponents();

    poc = new ArrayList<Pocitadlo>();
    rnd = new Random();

//    Pocitadlo tmp = new Pocitadlo(100, 40, 40, getFont());
//    tmp.addActionListener(this);
//    this.add(tmp);
//    tmp.start();
  }

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    int val, x, y;

    val = 20;
    x = (this.getWidth() / 2) - 10 + rnd.nextInt(20);
    y = (this.getHeight() / 2) - 10 + rnd.nextInt(20);

    try{
      val = Integer.parseInt(txtCounterValue.getText());

      Pocitadlo tmp = new Pocitadlo(val, x, y, getFont());
      tmp.addActionListener(this);
      poc.add(tmp);
      tmp.setVisible(true);
      tmp.start();
      this.add(tmp);
      this.setTitle("Počet počítadiel: " + this.getComponentCount());
      repaint();
      tmp.repaint();
    } catch(Exception e){
      JOptionPane.showMessageDialog(this, "Nesprávne zadaná alebo prázdna hodnota počítadla. Hodnota musí byť     celé číslo.", "Chyba", JOptionPane.ERROR_MESSAGE);
    }
  }

  @Override
  public void actionPerformed(ActionEvent e){
    if(e.getActionCommand().equals("counterFinished")){
      Pocitadlo tmp = (Pocitadlo)e.getSource();

      poc.remove(tmp);
      this.setTitle("Počet počítadiel: " + poc.size());
      this.remove(tmp);
    }
  }

これが私が追加しているJComponentsのコードであり、単純に描画されることを期待しています。

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;
import javax.swing.Timer;

public class Pocitadlo extends JComponent implements MouseListener, ActionListener {
  private int maxValue, value;
  private Boolean isRunning, isDisplayed;
  private Timer valueTimer, blinkTimer;
  private ActionListener actionListener;
  private Font font;

  public Pocitadlo(int timeout, int x, int y, Font f){
    isRunning = false;
    isDisplayed = true;
    maxValue = value = timeout;

    valueTimer = new Timer(1000, this);
    valueTimer.setActionCommand("valueTimer");

    blinkTimer = new Timer(200, this);
    blinkTimer.setActionCommand("blinkTimer");

    this.setBounds(x, y, 100, 50);
  }

  public void start(){
    isRunning = true;
    valueTimer.start();
  }

  public void stop(){
    isRunning = false;
    valueTimer.stop();
  }

  @Override
  public void actionPerformed(ActionEvent e){
    if(e.getActionCommand().equals("valueTimer")){
      value--;

      if(actionListener != null){
        repaint();
        actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterTick"));
      }

      if(value == 0 && actionListener != null){
        isRunning = false;
        valueTimer.stop();
        actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
      }
      if(value < maxValue / 2 && !blinkTimer.isRunning()) blinkTimer.start();
    }

    if(e.getActionCommand().equals("blinkTimer")){
      isDisplayed = !isDisplayed;
      repaint();
    }
  }

  public void addActionListener(ActionListener listener){
    actionListener = listener;
  }

  @Override
  public void mouseClicked(MouseEvent e) {
    value += 5000;
    if(value > maxValue) value = maxValue;
    repaint();
  }

  @Override
  public void paintComponent(Graphics g){
    g.setColor(Color.red);
    g.fillRect(getX(), getY(), getWidth(), getHeight());
    if(isDisplayed){
      g.setColor(Color.green);
      g.fillRect(getX(), getY(), getWidth(), getHeight());
      g.setColor(Color.black);
      //g.setFont(font);
      g.drawString(value + "/" + maxValue, 0, 0);
    }

    //super.paintComponent(g);
  }
}
  1. これは何の結果にもなりません-JComponentsが作成され、少なくともArrayListに正しく追加され、そのpaintComponentメソッドが実行され、タイマーイベントと同様に、カウントダウンが0に達すると、コンポーネントも少なくともArrayListから正しく削除されますが、何かを描くと、理由がわかりません。

  2. frmMainコンストラクターのコメント付きコードは機能し、コメントなしの場合はJComponentを描画することに注意してください...まあ...長方形だけでテキストは描画されませんが、それは別の問題だと思います。 'それも喜んで手伝ってくれます、嬉しいです。

  3. また、アクションイベントとリスナーを誤って使用している場合は、無視してください。私はJavaの初心者であり、正しく行う方法を知りたいのですが、後で、このコードを機能させる必要があります。問題に焦点を合わせてください、ありがとう。

  4. はい、コンポーネントに渡されたフォントのように、いくつかの死んだものがあります。それらは、drawStringを機能させるための私の試みの残りです。

4

1 に答える 1

3

あなたのプロジェクトは、Swingでのペイントがどのように機能するかについての多くの本当に基本的な誤解に苦しんでいます。

(私がテストした時点で)あなたは完全なコードを提供していなかったので、私はいくつかの仮定をしなければなりませんでした。

あなたの期待は、のコンテンツペインがレイアウトJFrameを使用していることです。nullこれをどのように管理し、フレームに他のコンポーネントを配置するかを理解するのは難しいと思います。いずれにせよ、私はあなたの「メイン」ビューとして機能する別のコンテナを分離しますPocitadlo。これにより、レイアウトマネージャーを引き続き使用して、他のコンポーネントも管理できます。

単に数値変換をキャッチするためPocitadloに、生成コード全体をトラップするのではないかと少し心配しています。try-catchすでにデフォルト値を適用しているので、変換をそれ自体でトラップし、try-catch失敗した場合は無視するのが妥当です(必要に応じてメッセージを表示します)。今、私は外から入ってくるので、これの必要性を見るかもしれません、それはちょうど私の目を引きました...

が完了した後も実行を継続valueTimer actionPerformedできる可能性があるため、コードは少し間違っています。代わりに、2つのステートメントを1つのステートメントにマージすることでこれを修正しました...blinkTimervalueTimerifif-else

if (value == 0 && actionListener != null) {
    isRunning = false;
    valueTimer.stop();
    actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
    blinkTimer.stop();
} else if (value < maxValue / 2 && !blinkTimer.isRunning()) {
    blinkTimer.start();
}

私は個人的に、JPaneloverを使用しJComponentます。 JPanelそもそも不透明です。

主な問題はあなたのpaintComponent方法にあります。

  1. 常にを呼び出す必要がsuper.paintComponentあり、不透明なコンポーネントでは最初に呼び出す必要があります。
  2. たとえば、ペイントするときにコンポーネントの位置を修正する必要があると考えているようですg.fillRect(getX(), getY(), getWidth(), getHeight());。これは実際には間違っています。グラフィックスコンテキストはすでに変換されているため、コンポーネント/グラフィックスのx/y位置は0x0に等しくなります。より良い説明については、AWTとSwingのPaintingを読んでください。ただし、基本的に、これは、ペイント領域の左上隅が0x0になったことを意味します。
  3. 最初の文字の左上隅からテキストが描かれているように思われます。これは実際には間違っています。テキストはそのベースラインに沿って描かれます。Fontsの上昇値でy位置を調整することにより、これを補う必要があります。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestRepaint01 {

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

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

                MainFrame frame = new MainFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class MainFrame extends javax.swing.JFrame implements ActionListener {

        ArrayList<Pocitadlo> poc;
        Random rnd;
        private JPanel body;

        /**
         * Creates new form frmMain
         */
        public MainFrame() {

            setLayout(new BorderLayout());

            poc = new ArrayList<Pocitadlo>();
            rnd = new Random();

            body = new JPanel(null);
            add(body);
            JButton btn = new JButton("Add");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int val, x, y;

                    val = 20;
                    x = (getWidth() / 2) - 10 + rnd.nextInt(20);
                    y = (getHeight() / 2) - 10 + rnd.nextInt(20);

//                    try {
//                        val = Integer.parseInt(txtCounterValue.getText());

                        Pocitadlo tmp = new Pocitadlo(val, x, y, getFont());
                        tmp.addActionListener(MainFrame.this);
                        GridBagConstraints gbc = new GridBagConstraints();
                        gbc.gridwidth = GridBagConstraints.REMAINDER;
                        gbc.weightx = 1;
                        gbc.fill = GridBagConstraints.HORIZONTAL;
                        poc.add(tmp);
                        tmp.start();
                        body.add(tmp);
                        body.repaint();
                        setTitle("Počet počítadiel: " + getComponentCount());
//                    } catch (Exception e) {
//                        JOptionPane.showMessageDialog(this, "Nesprávne zadaná alebo prázdna hodnota počítadla. Hodnota musí byť     celé číslo.", "Chyba", JOptionPane.ERROR_MESSAGE);
//                    }
                }
            });
            add(btn, BorderLayout.SOUTH);

        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("counterFinished")) {
                System.out.println("Counter finished");
                Pocitadlo tmp = (Pocitadlo) e.getSource();

                poc.remove(tmp);
                this.setTitle("Počet počítadiel: " + poc.size());
                body.remove(tmp);
//                body.revalidate();
                body.repaint();
            }
        }

    }

    public class Pocitadlo extends JPanel implements MouseListener, ActionListener {

        private int maxValue, value;
        private Boolean isRunning, isDisplayed;
        private Timer valueTimer, blinkTimer;
        private ActionListener actionListener;
        private Font font;

        public Pocitadlo(int timeout, int x, int y, Font f) {
            isRunning = false;
            isDisplayed = true;
            maxValue = value = timeout;

            valueTimer = new Timer(1000, this);
            valueTimer.setActionCommand("valueTimer");

            blinkTimer = new Timer(200, this);
            blinkTimer.setActionCommand("blinkTimer");

            this.setBounds(x, y, 100, 50);
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            stop();
            blinkTimer.stop();
        }

        public void start() {
            isRunning = true;
            valueTimer.start();
        }

        public void stop() {
            isRunning = false;
            valueTimer.stop();
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("valueTimer")) {
                value--;
                System.out.println("value = " + value);

                if (actionListener != null) {
                    repaint();
                    actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterTick"));
                }

                if (value == 0 && actionListener != null) {
                    isRunning = false;
                    valueTimer.stop();
                    actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
                    blinkTimer.stop();
                } else if (value < maxValue / 2 && !blinkTimer.isRunning()) {
                    blinkTimer.start();
                }
            }

            if (e.getActionCommand().equals("blinkTimer")) {
                System.out.println("Blink");
                isDisplayed = !isDisplayed;
                repaint();
            }
        }

        public void addActionListener(ActionListener listener) {
            actionListener = listener;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            value += 5000;
            if (value > maxValue) {
                value = maxValue;
            }
            repaint();
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }        

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            g.setColor(Color.red);
            // location bad
            g.fillRect(0, 0, getWidth(), getHeight());
            if (isDisplayed) {
                g.setColor(Color.green);
                g.fillRect(0, 0, getWidth(), getHeight());
                g.setColor(Color.black);
                //g.setFont(font);
                FontMetrics fm = g.getFontMetrics();
                g.drawString(value + "/" + maxValue, 0, fm.getAscent());
            }

            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);

        }

        @Override
        public void mousePressed(MouseEvent e) {
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

    }

}

あなたが遭遇した問題はどれも非常に重大ではなく(確かに、あなたのプログラムはあなたが望むことをしません)、あなたがあなたのコード能力の最高の瞬間に到達したことを示唆します。私はまったく同じ間違いをしたので、これを言います...;)

2Dグラフィックスカスタムペインティングを詳しく見てみましょう

また、Javaプログラミング言語のコード規則についても見ていきます。従わないと、単に人々を困らせるからです;)

于 2013-03-27T00:32:06.377 に答える