数字未显示在JFrame上

时间:2012-11-26 02:51:30

标签: java multithreading swing jframe paint

这是让数字出现的主题:

    class CoOrdCounter extends Thread{
    public void run(){
        try{
            while(true){
                    Thread.sleep(500);
                    printX = cow.x;
                    printY = cow.y;
            }
        }catch(Exception e){}
    }
}
//Of course I also have CoOrdCounter co = new CoOrdCounter; co.start();

然后......
g.drawString("Co-ords: ("+printX+","+printY+")",50,100); 它始终显示(0,0),可能是因为int printX = 0, printY = 0;。这意味着变量根本没有改变......为什么?我该怎么做才能做到这一点......? [PLEASE] 我知道我不应该使用paint()但我是初学者 - 中级所以...
[编辑] 现在MadProgrammer提到它,我收到了一个EventDispatchThread错误。
[编辑2] 我理解使用Timer@MadProgrammer如何使用您的代码段获取cow.xcow.y
[编辑3] 如果您输入密钥pKeyListener将启动Thread Sliderthread的实例。
[更新课程2(真实的)]

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.io.*;
import java.net.*;
@SuppressWarnings({"serial","rawtypes","unchecked"})
public class CowbenderI extends JFrame implements MouseListener, KeyListener{

CoOrdCounter co;
Counter cnt;
Icon icon = new ImageIcon("resources/img/cow.png");
int focusX = 0, focusY = 0, counter = 0;
ArrayList lines = new ArrayList();
Point2D.Double start;
final Color BROWN = new Color(156,93,82);
Slider thread;
Rectangle cow = null;
boolean drawGuy = false, useFinal = false, checkedForWin = false, alive = true;
int finalTime = 0;
int printX = 0, printY = 0;
public CowbenderI(){
    super("Cowbender I - \"Slope Run\"");
    setSize(700,700);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    addMouseListener(this);
    addKeyListener(this);

    cnt = new Counter();
    cnt.go = false;
    cnt.start();
    co = new CoOrdCounter();
    co.go = false;
    co.start();
}

public void paint(Graphics g){
    super.paint(g);
    try{
        g.setColor(Color.WHITE);
        g.fillRect(-2000, -2000, 5000, 5000);
        URL url = this.getClass().getResource("resources/img/world/slope.png");
        Image bckgrnd = Toolkit.getDefaultToolkit().getImage(url);
        g.drawImage(bckgrnd,0,0,this);
    }catch(Exception e){}
    g.setColor(BROWN);
    for(int i = 0; i < lines.size(); i++){
        Line2D.Double temp = (Line2D.Double) lines.get(i);
        int x1 = Integer.parseInt(""+Math.round(temp.getX1()));
        int x2 = Integer.parseInt(""+Math.round(temp.getX2()));
        int y1 = Integer.parseInt(""+Math.round(temp.getY1()));
        int y2 = Integer.parseInt(""+Math.round(temp.getY2()));

        g.drawLine(x1-focusX,y1-focusY,x2-focusX,y2-focusY);
    }

    if(drawGuy){
        try{
            g.setFont(new Font("Arial",Font.BOLD,16));
            if(useFinal == false) g.drawString("Current Time: "+counter,50,50);
            else g.drawString("Current Time: "+finalTime,50,50);
            g.drawString("Co-ords: ("+printX+","+printY+")",50,100);
            if(alive == true){
                URL url = this.getClass().getResource("resources/img/world/char.png");
                Image image = Toolkit.getDefaultToolkit().getImage(url);
                g.drawImage(image, cow.x-focusX, cow.y-focusY, this);
            }
            else{
                URL url = this.getClass().getResource("resources/img/world/deadchar.png");
                Image image = Toolkit.getDefaultToolkit().getImage(url);
                g.drawImage(image, cow.x-focusX, cow.y-focusY, this);
                    if(checkedForWin == false){
                        finalTime = counter;
                        useFinal = true;
                        checkWin();
                    }
                }
        } catch(Exception exc){}
        focusX = cow.x-100;
        focusY = cow.y-100;
    }
}

public void checkWin(){
    if(finalTime >= 45){
        JOptionPane.showMessageDialog(null,"You won!\nThe farmer got tired and ran back!","Cowbender I - The Slope",JOptionPane.INFORMATION_MESSAGE,icon);
        System.exit(0);
    }
}

public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){
    start = new Point2D.Double(e.getX()+focusX,e.getY()+focusY);
}
public void mouseReleased(MouseEvent e){
    Point2D.Double end = new Point2D.Double(e.getX()+focusX,e.getY()+focusY);
    lines.add(new Line2D.Double(start,end));
    repaint();
}
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
    if(e.getKeyChar()=='w'||e.getKeyChar()=='W'){
        focusY-=100;
        repaint();
    }
    if(e.getKeyChar()=='a'||e.getKeyChar()=='A'){
        focusX-=100;
        repaint();
    }
    if(e.getKeyChar()=='s'||e.getKeyChar()=='S'){
        focusY+=100;
        repaint();
    }
    if(e.getKeyChar()=='d'||e.getKeyChar()=='D'){
        focusX+=100;
        repaint();
    }
    if(e.getKeyChar()=='p'||e.getKeyChar()=='P'){
        alive = true;
        counter = 0;
        cnt.go = true;
        co.go = true;
        useFinal = false;
        thread = new Slider();
        thread.start();
        thread.action(true);
    }
    if(e.getKeyChar()=='z'||e.getKeyChar()=='Z'){
        lines.remove(lines.size()-1);
        repaint();
    }
    if(e.getKeyChar()=='x'||e.getKeyChar()=='X'){
        int response = milkSwing.confirmBox(null, "Do you really want to remove all of your summoned earth?", "Cowbender - The Slope", JOptionPane.YES_NO_OPTION);
        if(response == JOptionPane.YES_OPTION) lines.clear();
        repaint();
    }
    if(e.getKeyChar()=='q'||e.getKeyChar()=='Q'){
        System.exit(0);
    }
}

class CoOrdCounter extends Thread{
    public boolean go = true;
    public void run(){
        try{
            while(true){
                if(go){
                    Thread.sleep(500);
                    printX = cow.x;
                    printY = cow.y;
                    repaint();
                }
            }
        }catch(Exception e){}
    }
}

class Counter extends Thread{
    public boolean go = true;
    public void run(){
        try{
            while(true){
                if(go){
                    Thread.sleep(1000);
                    counter++;
                }
            }
        } catch(Exception e){}
    }
}

private class Slider extends Thread{
    double velocity, gravity;
    boolean go = false;
    public void run(){
        if(go){
            initGuy();
            velocity = 0;
            gravity = 1;
        }
        while(go){
            try{
                Line2D.Double lineTaken = null;
                boolean onLine = false;
                int firstOnLine = -1;
                for(int i = lines.size()-1; i>=0; i--){
                    Line2D.Double temp = (Line2D.Double) lines.get(i);
                    if(temp.intersects(cow.x,cow.y,50,50)){
                        lineTaken = temp;
                        onLine = true;
                        if(firstOnLine!=i){
                            firstOnLine = i;
                            gravity = 0;
                        }
                        break;
                    }
                }
                if(onLine){
                    double grav = (lineTaken.y2-lineTaken.y1)/50;
                    double vlct = (lineTaken.x2-lineTaken.x1)/100;
                    if(velocity<5)velocity+=vlct;
                    if(gravity<2.5)gravity+=grav;
                }
                else{
                    gravity+=.2;
                }
                cow.x+=velocity;
                cow.y+=gravity;
                if(cow.x > 10000) alive = false;

                Thread.sleep(75);
                repaint();
            }catch(Exception e){break;}
        }
    }
    public void action(boolean b){
        go = b;
    }
    public void initGuy(){
        Line2D.Double firstLine = (Line2D.Double) lines.get(0);
        int x = Integer.parseInt(""+Math.round(firstLine.x1));
        int y = Integer.parseInt(""+Math.round(firstLine.y1));
        cow = new Rectangle(x+90,y-60,50,50);
        drawGuy = true;
    }
}
/**
 * @param args
 */
public static void main(String[] args) {
    CowbenderI g = new CowbenderI();

}
}<br />

[编辑4] @MadProgrammer不工作:
enter image description here

1 个答案:

答案 0 :(得分:5)

您需要告诉Swing您要更新UI。在您遇到问题的情况下,因为它可能会违反与事件调度线程的合同(您不应该从事件调度线程以外的任何线程更新UI)

我在下面的示例中使用了一个简单的javax.swing.Timer,它克服了这个问题

public class PrintNumbers {

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

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

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new PrintPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PrintPane extends JPanel {

        private int printX;
        private int printY;

        public PrintPane() {
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    printX = (int) Math.round(Math.random() * 1000);
                    printY = (int) Math.round(Math.random() * 1000);
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int width = getWidth() - 1;
            int height = getHeight() - 1;
            FontMetrics fm = g.getFontMetrics();
            String text = printX + "x" + printY;
            int x = (width - fm.stringWidth(text)) / 2;
            int y = ((height - fm.getHeight()) / 2) + fm.getAscent();
            g.drawString(text, x, y);
        }

    }

}

<强>已更新

来自示例代码。

首先,您的示例代码错误的列表......

  • 没有理由延伸JFrame或覆盖paint方法。您最好从JPanel延伸并覆盖paintComponent。首先,这将为您提供自动双缓冲,其次,它将为您提供灵活的部署选项(将面板添加到JFrameJApplet
  • 您的线程管理需要更多工作。在while循环中运行没有做任何事情的线程(虽然go为false)正在浪费CPU,因为这些线程仍然需要安排运行。请仔细阅读Concurrency,特别是Synchronization和锁
  • KeyListener上使用key bindings API。它具有更好的焦点控制(组件不必具有焦点以触发操作)并生成可插入和可重用的代码。
  • 为您的事件监听器使用inner classes。当您真的不想
  • 时,它将减轻您通过主类公开事件处理程序方法的需要
  • 在实际可行的情况下,应避免使用空的异常块。如果出现问题,catch (Exception e) {}不会告诉你任何事情。至少你应该记录异常。

至于你的问题..

首先制作CoOrdCounter#goCounter#goSlider#goCow volatile

我离开了CoOrdCounter#go并能够正确地看到打印到控制台的结果(由于上述原因,你的图形无法在我的机器上运行)