首先,大家好!
我遇到了一个很大的问题:我需要构建一个程序,它包含构建一个包含5个方块和一个按钮的java swing接口。按钮功能是在方块内画一个圆圈。我有这个代码,但我不知道如何继续。
Frame类:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
public class Window extends JFrame{
private static Pane pane;
private Window(){
setResizable(false);
setVisible(true);
setBounds(0,0,350,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){
Window window = new Window();
window.setLocationRelativeTo(null);
pane = new Pane();
window.add(pane);
}
}
窗格类:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JLayeredPane;
public class Pane extends JPanel implements ActionListener{
private JButton next;
public Pane(){
setBounds(0,0,350,200);
setVisible(true);
setLayout(null);
repaint();
next = new JButton("Next");
next.setBounds(125,125,100,30);
next.addActionListener(this);
add(next);
}
public void actionPerformed (ActionEvent e){
Object source = e.getSource();
if (source == next){
Graphics g = this.getGraphics();
drawing(g);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawRect(50,50,50,50);
g.drawRect(100,50,50,50);
g.drawRect(150,50,50,50);
g.drawRect(200,50,50,50);
g.drawRect(250,50,50,50);
}
private int times = 0;
public void drawing(Graphics g){
if(times<5){
g.setColor(Color.RED);
g.fillOval(50+times*50, 50, 50, 50);
times++;
}
}
}
我有这些问题和疑问:
非常感谢大家!
答案 0 :(得分:3)
//Graphics g = this.getGraphics();
不要使用getGraphics()来绘画。这幅画只是暂时的,当组件重新粉刷时会丢失。
所有绘画必须在paintComponent()
方法中完成。这意味着您需要在类中设置一个属性,告诉paintComponent()
要绘制的内容。
这样做的一种方法是保持要绘制的List
个对象。然后在paintComponent()
方法中迭代List
并绘制对象。
因此,您可以使用以下代码创建List:
List<Shape> shapes = new ArrayList<Shape>();
Shape
界面允许您表示几何形状,如圆形,矩形,多边形等。然后,当您想要绘制第一个圆时,您可以使用以下代码向列表添加圆形:
shapes.add( new Ellipse2D.Double(50, 50, 50, 50) );
最后在paintComponent()方法中,绘制矩形后,添加代码以在List中绘制Shapes。
Graphics2D g2d = (Graphics2D)g.create();
for (Shape shape: shapes)
{
g2d.setColor( Color.RED );
g2d.fill( shape );
}
g2d.dispose()
因此,每当您单击下一个按钮时,清除列表并添加一个新的Shape以进行绘制。或者,如果您没有清除列表,那么您可以添加更多圈子,并且它们都将被绘制。
答案 1 :(得分:1)
这些是一些东西,你没有做正确的意义。
JFrame
的可见属性设置为可见,并使其实现其大小。Absolute Layout
,在大多数情况下应该避免使用{<1}}。Graphics
对象,哪一个应该避免,而是默认使用Java paintComponent ( ... )
方法提供的那个看一下这个例子:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawingCircleExample {
private JPanel drawingBoard;
private JButton button;
private static final int GAP = 5;
private void displayGUI () {
JFrame frame = new JFrame ( "" );
frame.setDefaultCloseOperation ( JFrame.DISPOSE_ON_CLOSE );
JPanel contentPane = new JPanel ();
contentPane.setLayout ( new BorderLayout ( GAP, GAP ) );
drawingBoard = new DrawingBoard ();
contentPane.add ( drawingBoard, BorderLayout.CENTER );
button = new JButton ( "Draw" );
button.addActionListener ( new ActionListener () {
@Override
public void actionPerformed ( ActionEvent ae ) {
DrawingBoard board = ( DrawingBoard ) drawingBoard;
board.setState ();
}
} );
contentPane.add ( button, BorderLayout.PAGE_END );
frame.setContentPane ( contentPane );
frame.pack ();
frame.setLocationByPlatform ( true );
frame.setVisible ( true );
}
public static void main ( String [] args ) {
Runnable runnable = new Runnable () {
@Override
public void run () {
new DrawingCircleExample ().displayGUI ();
}
};
EventQueue.invokeLater ( runnable );
}
}
class DrawingBoard extends JPanel {
private static final int TOTAL_RECTANGLES = 5;
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
private static final int RADIUS = 50;
private static final int X = 50;
private static final int Y = 50;
private int counter;
private int moveXBy;
private boolean isActive;
private int count;
public DrawingBoard () {
setOpaque ( true );
counter = 0;
count = 0;
isActive = false;
moveXBy = ( RADIUS + ( counter ) * RADIUS );
}
public boolean setState () {
isActive = true;
System.out.println ( "Outside MoveXBy: " + moveXBy );
++counter;
counter %= TOTAL_RECTANGLES;
int x = ( RADIUS + ( counter ) * RADIUS );
if ( moveXBy != x ) {
System.out.println ( "Inside First MoveXBy: " + moveXBy );
repaint ( moveXBy, RADIUS, X, Y );
moveXBy = x;
System.out.println ( "Inside Second MoveXBy: " + moveXBy );
repaint ( moveXBy, RADIUS, X, Y );
}
return isActive;
}
@Override
public Dimension getPreferredSize () {
return new Dimension ( WIDTH, HEIGHT );
}
@Override
protected void paintComponent ( Graphics g ) {
super.paintComponent ( g );
g.drawRect ( 50, RADIUS, X, Y );
g.drawRect ( 100, RADIUS, X, Y );
g.drawRect ( 150, RADIUS, X, Y );
g.drawRect ( 200, RADIUS, X, Y );
g.drawRect ( 250, RADIUS, X, Y );
g.setColor ( Color.RED );
g.fillOval ( moveXBy, RADIUS, X, Y ) ;
}
}
关于评论的编辑:
所有图形用户界面需要某种主要应用程序框架才能显示。在 Swing 中,这是javax.swing.JFrame
的一个实例。因此,我们的第一步是实例化这个类,并确保一切按预期工作。请注意,在 Swing 中编程时,您的GUI创建代码应放在事件调度线程(EDT)上,有关Concurrency in Swing的更多信息。这将防止可能导致僵局的潜在竞争条件。
DrawingBoard
也会覆盖getPreferredSize,它会返回所需的面板宽度和高度(在这种情况下,400
是width
,300
是因此,DrawingCircleExample
类不再需要指定帧的大小(以像素为单位)。它只是将面板添加到框架,然后调用pack。
paintComponent
方法是进行所有自定义绘制的地方。此方法由javax.swing.JComponent
定义,然后由子类重写以提供其自定义行为。它的唯一参数是java.awt.Graphics对象,它公开了许多绘制2D形状和获取有关应用程序图形环境的信息的方法。在大多数情况下,此方法实际接收的对象将是java.awt.Graphics2D(Graphics子类)的实例,它为复杂的2D图形渲染提供支持。
大多数标准Swing组件的外观都由单独的“UI Delegate”对象实现。 super.paintComponent(g)的调用将图形上下文传递给组件的UI委托,该委托绘制了面板的背景。
为了使我们的自定义绘画尽可能高效,我们将跟踪 X坐标(在我们的案例中为moveXBy
变量)并仅重新绘制已更改的屏幕区域。建议的最佳做法是尽可能高效地运行应用程序。
调用repaint
方法。此方法由java.awt.Component
定义,并且是允许您以编程方式重绘任何给定组件的表面的机制。它有一个无参数版本(重新绘制整个组件)和一个多参数版本(仅重新绘制指定区域。)此区域也称为剪辑。调用multi-arg版本的repaint需要花费一些额外的精力,但保证你的绘画代码不会浪费周期重新绘制屏幕上没有改变的区域。
因为我们手动设置剪辑,所以setState
方法不会调用repaint
方法,而是调用两次。第一次调用告诉Swing重新绘制以前椭圆形的组件区域(继承的行为使用UI委托用当前背景颜色填充该区域。)第二次调用绘制当前椭圆形的组件区域。值得注意的一点是,尽管我们已在同一事件处理程序中连续两次调用repaint
,但 Swing 足够智能,可以获取该信息并重新绘制屏幕中的所有部分一次油漆操作。换句话说, Swing 不会连续两次重新绘制该组件,即使这是代码似乎正在执行的操作。