Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 仅在鼠标悬停时更改字母的颜色_Java_Swing_Paintcomponent_Repaint_Mousehover - Fatal编程技术网

Java 仅在鼠标悬停时更改字母的颜色

Java 仅在鼠标悬停时更改字母的颜色,java,swing,paintcomponent,repaint,mousehover,Java,Swing,Paintcomponent,Repaint,Mousehover,我有一个Jframe,有两个按钮:“a”和“B”。单击按钮“A”应在JPanel中显示大写字母A。仅在鼠标悬停时,画布中的任何“A”字母都应显示为红色。当鼠标离开时,文本颜色应恢复为黑色 我已经为此编写了代码,它只工作一次。字母“A”变为红色,但不会变回黑色。此外,它不适用于多个“A” JFrame的代码: import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; im

我有一个Jframe,有两个按钮:“a”和“B”。单击按钮“A”应在JPanel中显示大写字母A。仅在鼠标悬停时,画布中的任何“A”字母都应显示为红色。当鼠标离开时,文本颜色应恢复为黑色

我已经为此编写了代码,它只工作一次。字母“A”变为红色,但不会变回黑色。此外,它不适用于多个“A”

JFrame的代码:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DrawFrame extends JFrame{
    private final int WIDTH = 500;
    private final int HEIGHT = 300;

    private GUIModel model;

    private JButton number1;
    private JButton number2;

    private JPanel numberPanel;
    private DrawPanel graphicsPanel;

    public DrawFrame()
    {
        this.model = new GUIModel(" ");

        createSelectionPanel();
        createGraphicsPanel();

        this.setSize(WIDTH, HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    private void createSelectionPanel()
    {
        numberPanel = new JPanel();

        ButtonListener listener = new ButtonListener();

        number1 = new JButton("A");
        number1.addActionListener(listener);

        number2 = new JButton("B");
        number2.addActionListener(listener);  

        numberPanel.setLayout(new GridLayout(2,2));
        numberPanel.add(number1);
        numberPanel.add(number2);

        this.add(numberPanel, BorderLayout.WEST);
    }

    private void createGraphicsPanel()
    {
        //instantiate drawing panel
        graphicsPanel = new DrawPanel(WIDTH, HEIGHT, model);
        //add drawing panel to right
        add(graphicsPanel);
    }

    private class ButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            model.setDisplayString(event.getActionCommand());
        }
    }

    //creates a drawing frame
    public static void main(String[] args)
    {
        DrawFrame draw = new DrawFrame();
    }   
}
JPanel的代码:

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;

public class DrawPanel extends JPanel{
    private static final long serialVersionUID = 3443814601865936618L;

    private Font font = new Font("Default", Font.BOLD, 30);

    private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
    private static final Color HOVER_TEXT_COLOR = Color.RED;
    private Color color = DEFAULT_TEXT_COLOR;

    private List<GUIModel> numberList = new ArrayList<GUIModel>();
    private GUIModel model;
    boolean mouseHover = false;

    public DrawPanel(int width, int height, GUIModel model){
        this.setPreferredSize(new Dimension(width, height));
        this.model = model;

        //set white background for drawing panel
        setBackground(Color.WHITE);

        //add mouse listeners
        MouseHandler mouseHandler = new MouseHandler();
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
    }

    void checkForHover(MouseEvent event) {
        FontMetrics metrics = getFontMetrics(font);

        Graphics g = getGraphics();
        Rectangle textBounds = metrics.getStringBounds("A", g).getBounds();
        g.dispose();

        int index = 0;
        while (index < numberList.size()) {
            Double x = numberList.get(index).getCoordinate().getX();
            Double y = numberList.get(index).getCoordinate().getY();

            textBounds.translate(x.intValue(), y.intValue());

            if (textBounds.contains(event.getPoint())) {
                color = HOVER_TEXT_COLOR;
            }
            else {
                color = DEFAULT_TEXT_COLOR;
            }
            index++;
        }
        repaint(textBounds);
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setFont(font);
        g.setColor(color);

        int index = 0;
        while (index < numberList.size()) {
            Double x = numberList.get(index).getCoordinate().getX();
            Double y = numberList.get(index).getCoordinate().getY();
            String display = numberList.get(index).getDisplayString();
            g.drawString(display, x.intValue(), y.intValue());
            index++;
        }

        if (model.getCoordinate() != null) {
            Point p = model.getCoordinate();            
            g.drawString(model.getDisplayString(), p.x, p.y);
            GUIModel number = new GUIModel();
            number.setCoordinate(p);
            number.setDisplayString(model.getDisplayString());
            numberList.add(number);
        }
    }

    //class to handle all mouse events
    private class MouseHandler extends MouseAdapter implements MouseMotionListener
    {
        @Override
        public void mousePressed(MouseEvent event)
        {
           model.setCoordinate(event.getPoint());
        }

        @Override
        public void mouseReleased(MouseEvent event)
        {
            DrawPanel.this.repaint();
        }

        @Override
        public void mouseEntered(MouseEvent event) {
            checkForHover(event);
        }

        @Override
        public void mouseMoved(MouseEvent event) {
            checkForHover(event);
        }
    }
}

任何帮助都将不胜感激。谢谢

有几个误解

  • Graphics#drawString
    不会在x/y位置绘制文本,因此x/y是
    字符串的左上角,而x/y位置是字体的基线,这意味着大部分文本绘制在y位置上方,有关详细信息,请参阅。这意味着,当您尝试计算文本的
    矩形时,它实际上低于绘制它的位置。相反,您需要使用
    y+ascent
    来正确定位文本
  • paintComponent
    可以出于多种原因随时调用,其中许多原因您无法控制。为此,
    paintComponent
    应仅用于绘制组件的当前状态,不得更新或修改组件的状态。因此,在方法中添加新的
    GUIModel
    是错误的,相反,它应该添加到
    MouseListener
    mouseClicked
    事件中
  • 您在很大程度上依赖于
    GUIModel
    变量。您应该仅在实际需要时创建模型
从概念上讲,这个例子解决了上面提到的大多数问题

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DrawFrame extends JFrame {

    private final int WIDTH = 500;
    private final int HEIGHT = 300;

//  private GUIModel model;
    private JButton number1;
    private JButton number2;

    private JPanel numberPanel;
    private DrawPanel graphicsPanel;

    public DrawFrame() {
//      this.model = new GUIModel(" ");

        createSelectionPanel();
        createGraphicsPanel();

        this.setSize(WIDTH, HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    private void createSelectionPanel() {
        numberPanel = new JPanel();

        ButtonListener listener = new ButtonListener();

        number1 = new JButton("A");
        number1.addActionListener(listener);

        number2 = new JButton("B");
        number2.addActionListener(listener);

        numberPanel.setLayout(new GridLayout(2, 2));
        numberPanel.add(number1);
        numberPanel.add(number2);

        this.add(numberPanel, BorderLayout.WEST);
    }

    private void createGraphicsPanel() {
        //instantiate drawing panel
        graphicsPanel = new DrawPanel(WIDTH, HEIGHT);
        //add drawing panel to right
        add(graphicsPanel);
    }

    private class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            graphicsPanel.setDisplayString(event.getActionCommand());
        }
    }

    //creates a drawing frame
    public static void main(String[] args) {
        DrawFrame draw = new DrawFrame();
    }

    public static class DrawPanel extends JPanel {

        private static final long serialVersionUID = 3443814601865936618L;

        private Font font = new Font("Default", Font.BOLD, 30);

        private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
        private static final Color HOVER_TEXT_COLOR = Color.RED;
        private Color color = DEFAULT_TEXT_COLOR;

        private List<GUIModel> numberList = new ArrayList<GUIModel>();
        boolean mouseHover = false;

        private String displayString;
        private GUIModel hoverModel;

        public DrawPanel(int width, int height) {
            this.setPreferredSize(new Dimension(width, height));

            //set white background for drawing panel
            setBackground(Color.WHITE);

            //add mouse listeners
            MouseHandler mouseHandler = new MouseHandler();
            this.addMouseListener(mouseHandler);
            this.addMouseMotionListener(mouseHandler);
        }

        protected Rectangle getBounds(GUIModel model) {
            FontMetrics metrics = getFontMetrics(font);
            Double x = model.getCoordinate().getX();
            Double y = model.getCoordinate().getY();

            Rectangle textBounds = new Rectangle(
                    x.intValue(),
                    y.intValue(),
                    metrics.stringWidth(model.getDisplayString()),
                    metrics.getHeight());
            return textBounds;
        }

        void checkForHover(MouseEvent event) {

            Rectangle textBounds = null;
            if (hoverModel != null) {
                textBounds = getBounds(hoverModel);
            }
            hoverModel = null;
            if (textBounds != null) {
                repaint(textBounds);
            }
            for (GUIModel model : numberList) {

                textBounds = getBounds(model);

                if (textBounds.contains(event.getPoint())) {
                    hoverModel = model;
                    repaint(textBounds);
                    break;
                }
            }
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setFont(font);
            g.setColor(DEFAULT_TEXT_COLOR);

            FontMetrics fm = g.getFontMetrics();
            for (GUIModel model : numberList) {
                if (model != hoverModel) {
                    Double x = model.getCoordinate().getX();
                    Double y = model.getCoordinate().getY();
                    String display = model.getDisplayString();
                    g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
                }
            }
            if (hoverModel != null) {
                g.setColor(HOVER_TEXT_COLOR);
                Double x = hoverModel.getCoordinate().getX();
                Double y = hoverModel.getCoordinate().getY();
                String display = hoverModel.getDisplayString();
                g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
            }

//          if (model.getCoordinate() != null) {
//              Point p = model.getCoordinate();
//              g.drawString(model.getDisplayString(), p.x, p.y);
////                GUIModel number = new GUIModel();
////                number.setCoordinate(p);
////                number.setDisplayString(model.getDisplayString());
////                numberList.add(number);
//          }
        }

        public void setDisplayString(String text) {
            displayString = text;
        }

        //class to handle all mouse events
        private class MouseHandler extends MouseAdapter implements MouseMotionListener {

            @Override
            public void mouseClicked(MouseEvent e) {
                GUIModel model = new GUIModel(displayString);
                model.setCoordinate(e.getPoint());
                numberList.add(model);
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent event) {
                checkForHover(event);
            }
        }
    }

    public static class GUIModel {

        private String displayString;
        private Point coordinate;

        public GUIModel() {
        }

        public GUIModel(String displayString) {
            this.displayString = displayString;
        }

        public void setDisplayString(String displayString) {
            this.displayString = displayString;
        }

        public String getDisplayString() {
            return displayString;
        }

        public Point getCoordinate() {
            return coordinate;
        }

        public void setCoordinate(int x, int y) {
            this.coordinate = new Point(x, y);
        }

        public void setCoordinate(Point coordinate) {
            this.coordinate = coordinate;
        }
    }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Font;
导入java.awt.FontMetrics;
导入java.awt.Graphics;
导入java.awt.GridLayout;
导入java.awt.Point;
导入java.awt.Rectangle;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionListener;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类DrawFrame扩展了JFrame{
专用最终整数宽度=500;
私人最终内部高度=300;
//私有gui模型;
私人按钮1号;
私人按钮2号;
私人JPanel号码panel;
私人拉丝板;
公共抽框(){
//this.model=新的GUIModel(“”);
createSelectionPanel();
createGraphicsPanel();
此.setSize(宽度、高度);
此.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
此.setVisible(true);
}
私有void createSelectionPanel(){
numberPanel=新的JPanel();
ButtonListener侦听器=新建ButtonListener();
编号1=新的按钮(“A”);
编号1.addActionListener(listener);
数字2=新的按钮(“B”);
编号2.addActionListener(listener);
numberPanel.setLayout(新网格布局(2,2));
数字面板添加(数字1);
数字面板添加(数字2);
添加(数字面板,BorderLayout.WEST);
}
私有void createGraphicsPanel(){
//实例化图形面板
graphicsPanel=新的绘图面板(宽度、高度);
//将绘图面板添加到右侧
添加(图形spanel);
}
私有类ButtonListener实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件){
graphicsPanel.setDisplayString(event.getActionCommand());
}
}
//创建绘图框
公共静态void main(字符串[]args){
DrawFrame draw=新的DrawFrame();
}
公共静态类DrawPanel扩展了JPanel{
私有静态最终长serialVersionUID=3443814601865936618L;
私有字体字体=新字体(“默认”,Font.BOLD,30);
私有静态最终颜色默认值\文本\颜色=Color.BLACK;
私有静态最终颜色悬停\文本\颜色=Color.RED;
专用颜色=默认的文本颜色;
private List numberList=new ArrayList();
布尔mouseHover=false;
私有字符串显示字符串;
私有图形用户界面模型;
公共绘图面板(内部宽度、内部高度){
此.setPreferredSize(新尺寸(宽度、高度));
//为绘图面板设置白色背景
挫折地面(颜色:白色);
//添加鼠标侦听器
MouseHandler MouseHandler=新的MouseHandler();
这是addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
受保护的矩形getBounds(GUI模型){
FontMetrics=getFontMetrics(字体);
Double x=model.getCoordinate().getX();
双y=model.getCoordinate().getY();
矩形textBounds=新矩形(
x、 intValue(),
y、 intValue(),
metrics.stringWidth(model.getDisplayString()),
metrics.getHeight());
返回文本边界;
}
void checkForHover(MouseEvent事件){
矩形textBounds=null;
if(hoverModel!=null){
textBounds=getBounds(hoverModel);
}
hoverModel=null;
如果(textBounds!=null){
重新绘制(文本边界);
}
用于(GUI模型模型:numberList){
textBounds=getBounds(模型);
if(textBounds.contains(event.getPoint())){
模型=模型;
重新绘制(文本边界);
打破
}
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DrawFrame extends JFrame {

    private final int WIDTH = 500;
    private final int HEIGHT = 300;

//  private GUIModel model;
    private JButton number1;
    private JButton number2;

    private JPanel numberPanel;
    private DrawPanel graphicsPanel;

    public DrawFrame() {
//      this.model = new GUIModel(" ");

        createSelectionPanel();
        createGraphicsPanel();

        this.setSize(WIDTH, HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    private void createSelectionPanel() {
        numberPanel = new JPanel();

        ButtonListener listener = new ButtonListener();

        number1 = new JButton("A");
        number1.addActionListener(listener);

        number2 = new JButton("B");
        number2.addActionListener(listener);

        numberPanel.setLayout(new GridLayout(2, 2));
        numberPanel.add(number1);
        numberPanel.add(number2);

        this.add(numberPanel, BorderLayout.WEST);
    }

    private void createGraphicsPanel() {
        //instantiate drawing panel
        graphicsPanel = new DrawPanel(WIDTH, HEIGHT);
        //add drawing panel to right
        add(graphicsPanel);
    }

    private class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            graphicsPanel.setDisplayString(event.getActionCommand());
        }
    }

    //creates a drawing frame
    public static void main(String[] args) {
        DrawFrame draw = new DrawFrame();
    }

    public static class DrawPanel extends JPanel {

        private static final long serialVersionUID = 3443814601865936618L;

        private Font font = new Font("Default", Font.BOLD, 30);

        private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
        private static final Color HOVER_TEXT_COLOR = Color.RED;
        private Color color = DEFAULT_TEXT_COLOR;

        private List<GUIModel> numberList = new ArrayList<GUIModel>();
        boolean mouseHover = false;

        private String displayString;
        private GUIModel hoverModel;

        public DrawPanel(int width, int height) {
            this.setPreferredSize(new Dimension(width, height));

            //set white background for drawing panel
            setBackground(Color.WHITE);

            //add mouse listeners
            MouseHandler mouseHandler = new MouseHandler();
            this.addMouseListener(mouseHandler);
            this.addMouseMotionListener(mouseHandler);
        }

        protected Rectangle getBounds(GUIModel model) {
            FontMetrics metrics = getFontMetrics(font);
            Double x = model.getCoordinate().getX();
            Double y = model.getCoordinate().getY();

            Rectangle textBounds = new Rectangle(
                    x.intValue(),
                    y.intValue(),
                    metrics.stringWidth(model.getDisplayString()),
                    metrics.getHeight());
            return textBounds;
        }

        void checkForHover(MouseEvent event) {

            Rectangle textBounds = null;
            if (hoverModel != null) {
                textBounds = getBounds(hoverModel);
            }
            hoverModel = null;
            if (textBounds != null) {
                repaint(textBounds);
            }
            for (GUIModel model : numberList) {

                textBounds = getBounds(model);

                if (textBounds.contains(event.getPoint())) {
                    hoverModel = model;
                    repaint(textBounds);
                    break;
                }
            }
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setFont(font);
            g.setColor(DEFAULT_TEXT_COLOR);

            FontMetrics fm = g.getFontMetrics();
            for (GUIModel model : numberList) {
                if (model != hoverModel) {
                    Double x = model.getCoordinate().getX();
                    Double y = model.getCoordinate().getY();
                    String display = model.getDisplayString();
                    g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
                }
            }
            if (hoverModel != null) {
                g.setColor(HOVER_TEXT_COLOR);
                Double x = hoverModel.getCoordinate().getX();
                Double y = hoverModel.getCoordinate().getY();
                String display = hoverModel.getDisplayString();
                g.drawString(display, x.intValue(), y.intValue() + fm.getAscent());
            }

//          if (model.getCoordinate() != null) {
//              Point p = model.getCoordinate();
//              g.drawString(model.getDisplayString(), p.x, p.y);
////                GUIModel number = new GUIModel();
////                number.setCoordinate(p);
////                number.setDisplayString(model.getDisplayString());
////                numberList.add(number);
//          }
        }

        public void setDisplayString(String text) {
            displayString = text;
        }

        //class to handle all mouse events
        private class MouseHandler extends MouseAdapter implements MouseMotionListener {

            @Override
            public void mouseClicked(MouseEvent e) {
                GUIModel model = new GUIModel(displayString);
                model.setCoordinate(e.getPoint());
                numberList.add(model);
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent event) {
                checkForHover(event);
            }
        }
    }

    public static class GUIModel {

        private String displayString;
        private Point coordinate;

        public GUIModel() {
        }

        public GUIModel(String displayString) {
            this.displayString = displayString;
        }

        public void setDisplayString(String displayString) {
            this.displayString = displayString;
        }

        public String getDisplayString() {
            return displayString;
        }

        public Point getCoordinate() {
            return coordinate;
        }

        public void setCoordinate(int x, int y) {
            this.coordinate = new Point(x, y);
        }

        public void setCoordinate(Point coordinate) {
            this.coordinate = coordinate;
        }
    }
}