java - 数字未显示在 JFrame 上

标签 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("坐标:("+printX+","+printY+")",50,100); 它总是显示(0,0),可能是因为int printX = 0, printY = 0;。所以这意味着变量根本没有改变......为什么?我应该如何使这项工作...?
[请]我知道我不应该使用 paint() 但我是初级中级所以...
[编辑] 现在 MadProgrammer 提到了它,我确实收到了 EventDispatchThread 错误。
[EDIT 2] 我了解使用 Timer 但是 @MadProgrammer 我如何获得 cow.xcow.y 使用您的代码片段?
[EDIT 3] 如果您键入键 p KeyListener 将启动 Thread 的实例 slider 线程
[UPDATE CLASS 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

最佳答案

您需要告诉 Swing 您想要更新 UI。在你的情况下,这会出现问题,因为它可能违反与事件调度线程的契约(Contract)(你永远不应该从事件调度线程以外的任何线程更新 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和锁
  • 使用key bindings API 通过 KeyListener。它具有更好的焦点控制(组件不必拥有焦点即可触发操作)并生成可插入和可重用的代码。
  • 利用inner classes为你的事件听众。当您确实不想这样做时,它将使您无需通过主类公开事件处理程序方法
  • 您应该尽可能避免使用空异常 block 。如果出现问题,catch (Exception e) {} 不会告诉您任何信息。至少您应该记录异常。

关于你的问题..

开始制作 CoOrdCounter#goCounter#goSlider#goCow volatile .

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

关于java - 数字未显示在 JFrame 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13558034/

相关文章:

multithreading - 如何在 Perl 中使用线程?

c# - 将同一文件从多个线程复制到多个目的地

c++ - openMP C++ 简单并行区域 - 输出不一致

java - 如何向 ARRAYLIST 添加数据

java - Spring集成tcp-connection-factory在回复之前关闭客户端连接

java - 从匿名内部类访问外部类最终局部变量

java - 这段代码哪里失败了?两种方法之间的区别

java - GUI不会刷新

java - JTextPane 未在 GridBagConstraints 上水平填充

java - .* 究竟是什么?在正则表达式中做什么? ".*?([a-m/]*).*"