我想编写一个应用程序,让您可以通过在 JFrame
左侧单击鼠标来绘制圆圈,并且所有点都会“镜像”到右侧。我遇到的第一个问题是,当我尝试在框架中实现此绘制机制时,没有出现圆圈。
public class Application{
int x,y;
private JPanel container;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Application().gui();
}
});
}
public void gui()
{
int height = 250;
int width = 700;
JFrame jframe = new JFrame();
container = new JPanel();
container.setLayout(new BorderLayout());
container.add(new DrawCircle(), BorderLayout.WEST);
container.setVisible(true);
jframe.add(container);
//jframe.add(new DrawCircle());
jframe.setSize(500,700);
jframe.setVisible(true);
jframe.setTitle("Title");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);
}
}
当我使用 container.add(new DrawCircle)
时,它可以(在整个框架上)工作,但如果我想添加约束,它就不行。
这是圆类:
public class DrawCircle extends JPanel implements MouseListener
{
ArrayList<Point> p = new ArrayList<Point>();
public DrawCircle()
{
addMouseListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(Point point : p)
{
g.fillOval(point.x,point.y,30,30);
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getY(), e.getX()));
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent arg0) {
}
}
最佳答案
让我们来看看您的问题:
The first problem I encountered was that when I try to implement this draw-mechanic in my frame, no circles appear.
这是因为每当您单击 DrawCircle
类中的某个位置时,您忘记调用 JPanel#revalidate()
和 JPanel#repaint()
。
因此,您可以将 mousePressed()
方法更改为:
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
revalidate();
repaint();
}
请注意,我还更改了 e.getX()
和 e.getY()
调用,因为它们位于错误的位置(除非您希望它们那样) )。
这将使你的圆圈出现,但是,你的 DrawCircle
真的很薄(我将这个图像的 JFrame
的高度更改为 200,否则它会是真的很高):
红色部分是您的DrawCircle
面板。
要解决此问题,您需要重写其 getPreferredSize()
方法:
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
这将使您的 JPanel
返回一半的大小,width
和 height
作为参数传递给构造函数,并且您的类DrawCircle
现在应该如下所示:
class DrawCircle extends JPanel implements MouseListener {
ArrayList<Point> p = new ArrayList<Point>();
int width = 0;
int height = 0;
public DrawCircle(int width, int height) {
this.width = width;
this.height = height;
addMouseListener(this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point point : p) {
g.fillOval(point.x, point.y, 30, 30);
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
revalidate();
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
输出将是这样的:
It works (on the whole frame) when I use container.add(new DrawCircle)
这是因为默认情况下 BorderLayout
将元素默认放置在 CENTER
区域,并且如果在其余方向(NORTH
)中没有其他内容, code>、SOUTH
等)它将占据整个空间。
现在让我们继续讨论如何解决您的问题:
我还对 Application
类进行了一些更改(在我的例子中,我将其重命名为 CustomPaintingInHalfFrame
):
这些变化是:
- 为
WIDTH
和HEIGHT
属性创建最终常量。 - 使用
BorderLayout
布局删除不必要的JPanel
,因为JFrame
默认情况下已经具有此布局,我只需添加我们的DrawClass
到它。 - 为
DrawCircle
面板绘制边框(因为您不希望在JFrame
的两个(左和右)部分之间进行划分,如 previous question 中所述您可以简单地将其删除(我建议您在测试时将其保留在那里,以便您知道左面板在哪里结束,右面板在哪里开始。 - 将
WIDTH/2
和HEIGHT
作为参数传递给DrawCircle
构造函数,以便它可以返回正确的Dimension
.
所以,我们的类现在应该如下所示:
public class CustomPaintingInHalfFrame {
int x, y;
public static final int WIDTH = 500;
public static final int HEIGHT = 200;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CustomPaintingInHalfFrame().gui();
}
});
}
@SuppressWarnings("serial")
public void gui() {
JFrame jframe = new JFrame("Title");
DrawCircle dc = new DrawCircle(WIDTH / 2, HEIGHT);
dc.setBorder(BorderFactory.createLineBorder(Color.RED));
jframe.add(dc, BorderLayout.WEST);
jframe.setSize(WIDTH, HEIGHT);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);
}
}
<小时/>
其他提示
我建议您将
DrawCircle
重命名为Circle
或类似名称。作为 convention ,类名称应该是名词将
gui()
方法重命名为createGui()
,因为作为类名称,方法 名称应为 >动词
关于java - 在 JPanel 的一侧绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41700866/