【问题标题】:JMenuItem only triggers from keyboard input and not clickJMenuItem 仅从键盘输入触发而不是单击
【发布时间】:2012-12-10 15:43:35
【问题描述】:

我使用 JFrame 用 Ja​​va 制作了一个简单的绘图程序(这是我第一次使用)。用户单击并拖动以绘制形状,但这并不重要。我有一个JMenuBar 有很多选项,比如形状类型、新建和退出。当用户单击new 按钮时,它应该清除屏幕。当用户点击 Ctrl+N 时,这工作得很好。但是,当单击按钮时,它根本不起作用。

我在 newItem 的 actionEvent 中放置了一个调试 System.out.println,当单击该项目时它打印得很好,但它实际上并没有擦除屏幕。知道是什么原因造成的吗?

我删除了程序的大部分内容,并留下了尽可能多的内容以查看问题。您仍然可以按住并拖动来绘制一个形状(直到您释放鼠标按钮后该形状才会出现),然后按 Ctrl+N 以清除屏幕,但单击新建不会这样做。

import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.*;

public class E3G04 extends JFrame implements WindowListener, ActionListener, MouseListener, MouseMotionListener
{
    //Variables are declared as volatile to ensure that they're always called from system RAM
    static volatile String type = "rectangle";
    static volatile Boolean fill = true;
    static Color lineColor = Color.BLACK;
    static Color fillColor = Color.RED;
    static int size = 1;

    CanvasEX cx = new CanvasEX();

    static boolean running = true;

    JMenuBar mb = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
            JMenuItem newItem = new JMenuItem("New");
            JMenuItem quitItem = new JMenuItem ("Quit");


    protected E3G04()
    {

        mb.add(fileMenu);
        fileMenu.add(newItem);
        fileMenu.add(quitItem);             
        newItem.setMnemonic('N');
        quitItem.setMnemonic('Q');
        newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));          
        newItem.addActionListener(this);
        quitItem.addActionListener(this);
        cx.setSize(800,600);
        cx.addMouseListener(this);
        cx.addMouseMotionListener(this);
        setJMenuBar(mb);
        setBounds(100,100,800,600);
        setLayout(new BorderLayout());
        add("Center",cx);
        addWindowListener(this);
        setResizable(true);
        setVisible(true);
    }

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

    public void stop()
    {
        newItem.removeActionListener(this);
        quitItem.removeActionListener(this);    
        dispose();
        System.exit(0);
    }

    public void actionPerformed(ActionEvent e)
    {
        Object o = e.getSource();

        if (o == newItem)
        {
            cx.erase = true;
            cx.repaint();
        }

        if (o == quitItem)
        {   
            running = false;
            stop();
        }

    }      

    public void mousePressed(MouseEvent m)
    {
        cx.start = m.getPoint();
        cx.end = cx.start;
        cx.cur = cx.start;
    }

    public void mouseDragged(MouseEvent m)
    {
        cx.cur = m.getPoint();
    }   

    public void mouseReleased(MouseEvent m)
    {
        cx.end = cx.cur;
        cx.repaint();
    }   
    public void itemStateChanged(ItemEvent e)
    {
        Object o = e.getSource();

    }
    public void windowClosing(WindowEvent e)
    {
        running = false;
        stop();
    }
    public void mouseClicked(MouseEvent m){}    
    public void mouseExited(MouseEvent m){}
    public void mouseEntered(MouseEvent m){}    
    public void mouseMoved(MouseEvent m){}
    public void windowClosed(WindowEvent e){}
    public void windowOpened(WindowEvent e){}
    public void windowActivated(WindowEvent e){}
    public void windowDeactivated(WindowEvent e){}
    public void windowIconified(WindowEvent e){}
    public void windowDeiconified(WindowEvent e){}
}


class CanvasEX extends Canvas
{
    Point start = new Point(100,100);
    Point cur = new Point(100,100);
    Point end = new Point(100,100);
    Image offscreen;
    boolean erase = false;

    public void update(Graphics g)
    {
        //This is adds the new stuff to the screen or erases the screen if erase is true
        Graphics buffer;
        if (offscreen == null)
        {
            offscreen = createImage(getWidth(), getHeight());
        }
        buffer = offscreen.getGraphics();
        if (erase)
        {
            buffer.setColor(getBackground());
            buffer.fillRect(0,0,800, 600);
            buffer.dispose();
            erase = false;
        }
        paint(buffer);
        g.drawImage(offscreen, 0, 0, this);
    }   

    public void paint(Graphics g)
    {
        Graphics buffer = g;
        if (erase)
        {
            g.dispose();
            erase = false;
        }   
        g.setColor(E3G04.lineColor);
        if (end.x > start.x && end.y > start.y)
            g.fillRect(start.x,start.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        if (end.x > start.x && end.y < start.y)
            g.fillRect(start.x,end.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));  
        if (end.x < start.x && end.y > start.y)
            g.fillRect(end.x, start.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        if (end.x < start.x && end.y < start.y)
            g.fillRect(end.x, end.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        g.setColor(E3G04.fillColor);
        if (end.x > start.x && end.y > start.y)
            g.fillRect(start.x + E3G04.size,start.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);
        if (end.x > start.x && end.y < start.y)
            g.fillRect(start.x + E3G04.size,end.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);  
        if (end.x < start.x && end.y > start.y)
            g.fillRect(end.x + E3G04.size, start.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);
        if (end.x < start.x && end.y < start.y)
            g.fillRect(end.x + E3G04.size, end.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);          
    }
}

【问题讨论】:

  • 你听说过数组和循环吗?如果你使用它们,你可以大大缩短代码。
  • 当然有。为什么要问?
  • 或者这段代码是不是某个程序生成的?
  • 为什么你对菜单项使用ItemListener,为什么不对所有菜单项使用ActionListener??
  • 哦,对了,我现在可以做到了。我之前使用的是 AWT 和常规的 MenuBar 而不是 JMenuBar,所以我使用的是 CheckboxMenuItems。我真的会很快改变这一点。不过,这与我的问题有关吗?因为 NewItem 正在使用 ActionListener

标签: java swing jframe menubar jmenubar


【解决方案1】:

如果您放弃了使用 AWT 的教授建议,请更改

class CanvasEX extends Canvas

.. 到..

class CanvasEX extends JPanel

&

public void paint(Graphics g)
{
    .. 

public void paintComponent(Graphics g)
{ 
  super.paintComponent(g);
  ..

然后你需要弄清楚如何让图纸持续存在。

【讨论】:

  • 感谢您到目前为止的帮助。就像我在上面的 cmets 中所说的那样,它使 New 按钮起作用,但现在窗口不是正常大小,即使我将 CanvasEX 对象设置为 800x600,并且 JFrame 的边界也设置为 800x600。而且,是的,存在让图纸持续存在的问题。我什至不知道从哪里开始,因为这是我第一次使用 Swing
  • 这是关于组件的自定义绘制,还是只是自定义绘制?我倾向于在BufferedImage 中执行后者,如here 所示。
  • 这只是一般的自定义绘画。无论如何,我认为我所做的基本上是一个缓冲图像。我在 CanvasEX 中的整个更新方法只是缓冲图像。再次感谢所有的帮助。我现在要睡觉了(因为这里是凌晨 3 点 10 分),但我会在起床后查看你的教程。它看起来很甜。
猜你喜欢
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多