[英]Java thread and graphics2d
i need a hint how to make my program to work properly. 我需要提示如何使我的程序正常工作。 I created a class that extends from JComponent.
我创建了一个从JComponent扩展的类。 I also managed to make the whole panel of white colors.
我还设法使整个面板变成白色。 Now i am trying to make that my thread Wolf will be painted on the JCOmponent and will move one time.
现在,我试图使我的线程Wolf将被绘制在JCOmponent上并将移动一次。 Unfortunately my code dont works and i think its because wolf is not being painted on the white board.
不幸的是,我的代码无法正常工作,我认为这是因为没有在白板上画狼。 How to change the program to make it work.
如何更改程序以使其起作用。 I will be grateful for help.
我将不胜感激。
public class Plansza extends JComponent implements ActionListener {
static int width = 500;
static int height = 500;
Ellipse2D wolf;
Ellipse2D hare;
// size of frame n x m (width,height)
public Dimension getPreferredSize(){
return new Dimension(width,height);
}
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
//draw a background
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
}
class Wilk implements Runnable{
private int x;
private int y;
//when creating a thread we get a first position of wolf
Wilk(int posx, int posy){
x=posx;
y=posy;
}
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
//draw a wolf
g.setColor(Color.BLUE);
wolf = new Ellipse2D.Double(x,y, 10, 10);
g2.fill(wolf);
}
public void run() {
x=x+5;
y=y+5;
repaint();
}
}
public static void main( final String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame window = new JFrame("Wilki vs Zajace");
Plansza p = new Plansza();
window.add(p);
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setVisible(true);
// Timer t = new Timer(10,p); //action listener referred to Plansza(1 cycle every 100miliseconds)
// t.start();
Wilk wolf = new Wilk(10,10);
Thread myWolf = new Thread(wolf);
myWolf.start();
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
Start by talking a look at Performing Custom Painting and Painting in AWT and Swing for details about how painting is performed in Swing. 首先介绍一下在AWT和Swing中执行自定义绘画和绘画,以获取有关在Swing中如何进行绘画的详细信息。
Take a look at Concurrency in Swing for details about dealing with Swing a threads. 查看Swing中的并发,以获取有关处理Swing线程的详细信息。
Basically, only a component on a displayed container will be painted. 基本上,仅显示容器上的一个组件会被绘制。 This means that only your
Plansza
will be painted, but only when it's added to a (directly or otherwise) something like JFrame
and the JFrame
is made visible. 这意味着将仅绘制您的
Plansza
,但仅在将它添加到(直接或其他方式)诸如JFrame
之类的东西时,才会显示JFrame
。
This means that Wilk
can never be painted and therefore it's paintComponent
method becomes somewhat pointless (in this context) 这意味着
Wilk
永远不会被绘制,因此它的paintComponent
方法变得毫无意义(在这种情况下)
What you could use is some way to communicate what you want to paint from your Wilk
(controller) to Plansza
(view). 您可以使用某种方式将想要从
Wilk
(控制器) Plansza
到Plansza
(视图)。 This is typically achieved via the use of some kind of model, which allows your controller to change it's state and your view to render that state. 这通常是通过使用某种模型来实现的,该模型允许您的控制器更改其状态,并通过视图呈现该状态。
For example... 例如...
This is a basic demonstration of a Model-Control-View implementation. 这是Model-Control-View实现的基本演示。
The model drives the view and the controller drives the model. 模型驱动视图,而控制器驱动模型。 In this way, so long as the contract of the model is meet, the various elements are independent of each other
这样,只要满足模型的约定,各个要素就相互独立
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PaintModel {
public static void main(String[] args) {
new PaintModel();
}
public PaintModel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
MutableModel model = new DefaultModel();
Controller controller = new Controller(model);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new View(model));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
controller.start();
}
});
}
public interface Model {
public Rectangle getBounds();
public Dimension getSize();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
public interface MutableModel extends Model {
public void update();
}
public class DefaultModel implements MutableModel {
private final Dimension size = new Dimension(200, 200);
private final Rectangle bounds = new Rectangle(95, 95, 10, 10);
private int xDelta = ((int) (Math.random() * 5)) + 1;
private int yDelta = ((int) (Math.random() * 5)) + 1;
private List<ChangeListener> changeListeners;
public DefaultModel() {
changeListeners = new ArrayList<>(25);
}
@Override
public void addChangeListener(ChangeListener listener) {
changeListeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
changeListeners.remove(listener);
}
protected void fireStateChanged() {
if (changeListeners.size() > 0) {
ChangeEvent evt = new ChangeEvent(this);
Iterator<ChangeListener> it = changeListeners.iterator();
while (it.hasNext()) {
ChangeListener listener = it.next();
listener.stateChanged(evt);
}
}
}
@Override
public Dimension getSize() {
return size;
}
@Override
public Rectangle getBounds() {
return bounds;
}
@Override
public void update() {
bounds.x += xDelta;
bounds.y += yDelta;
if (bounds.x < 0) {
bounds.x = 0;
xDelta *= -1;
} else if (bounds.x + bounds.width > size.width) {
bounds.x = size.width - bounds.width;
xDelta *= -1;
}
if (bounds.y < 0) {
bounds.y = 0;
yDelta *= -1;
} else if (bounds.y + bounds.height > size.height) {
bounds.y = size.height - bounds.height;
yDelta *= -1;
}
fireStateChanged();
}
}
public class Controller extends Thread {
private MutableModel model;
public Controller(MutableModel model) {
this.model = model;
setDaemon(true);
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
model.update();
}
}
}
public class View extends JComponent implements ChangeListener {
private Model model;
public View(Model model) {
this.model = model;
this.model.addChangeListener(this);
setBackground(Color.WHITE);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(model.getSize());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
Rectangle bounds = model.getBounds();
g2d.setColor(Color.BLUE);
g2d.drawOval(bounds.x, bounds.y, bounds.width, bounds.height);
g2d.dispose();
}
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
}
}
In many modern languages the UI runs on the main thread, and you cannot modify it (or you shouldn't at least) from another thread. 在许多现代语言中,UI在主线程上运行,并且您不能(或者至少不应)从另一个线程对其进行修改。 ( http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html )
( http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html )
Although repaint(), and revalidate() are threadsafe and they have their own invokeAndWait, you MUST create the UI using something like this. 尽管repaint()和revalidate()是线程安全的,并且它们具有自己的invokeAndWait,但是您必须使用类似的方法来创建UI。
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
Therefore you are creating a paint wolf thread each time you paint the main panel. 因此,每次绘制主面板时,都会创建一个绘制狼线。
Also Oracle suggest to call super.paintComponent(g);
Oracle也建议调用
super.paintComponent(g);
in http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html 在http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html中
I recommend you to read completely the Oracle Swing guide, and then try to modify the Flipper coin example to work as you want ( http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/concurrency/FlipperProject/src/concurrency/Flipper.java ) 我建议您完全阅读Oracle Swing指南,然后尝试修改Flipper硬币示例以使其按需工作( http://docs.oracle.com/javase/tutorial/displayCode.html?code=http:// docs.oracle.com/javase/tutorial/uiswing/examples/concurrency/FlipperProject/src/concurrency/Flipper.java )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.