我正在尝试将关键侦听器添加到 Java 中的 JPanel

问题描述 投票:0回答:1

有很多要理解的,所以坚持我。我在 JScrollPane 中有一个 JPanel,它在 JTabbedPane 中,而 JTabbedPane 在 JFrame 中。在这个过程中的某个地方,我失去了添加关键听众的能力。

我用这个来设置我的 JFrame

public class Cartographer {

    private final JFrame frmMyWorld = new JFrame();
    /**
     * set up our toolbar
     */
    private final JButton addTabb = new JButton("Create New Workspace");
    
    
    //this is where I create the new tabbed pane
    private static JTabbedPane tabbedPane;
    private int numberOfTabbs;
    public static boolean isScrolling;
    private static JSlider zoomer;
    
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Cartographer window = new Cartographer();
                    window.frmMyWorld.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Cartographer() { 
        initialize();
        createEvents();
    }

然后我初始化:

private void initialize() {
        
        frmMyWorld.setTitle("My World");
        frmMyWorld.setBounds(0, 0, 1450, 805);
        frmMyWorld.getContentPane().setBackground(new Color(100,100,100));
        frmMyWorld.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        newTab();
        isScrolling = true;

        //this sets up my slider which I'm using to zoom
        zoomer = new JSlider();
        zoomer.setMinimum(-1000);
        zoomer.setMaximum(1000);
        zoomer.setValue(1000);
        zoomer.setOrientation(SwingConstants.VERTICAL);
        zoomer.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                if(isScrolling) {
                    hPortion = getHPortion();
                    vPortion = getVPortion();
                }
                isScrolling = false;
                int hScale = (int) getSelectedPane().getHorizontalScrollBar().getMaximum();
                int vScale = (int) getSelectedPane().getVerticalScrollBar().getMaximum();
                getSelectedSpace().setZoomFactor(Math.pow(2, (double) zoomer.getValue()/250 - 4));
                getSelectedSpace().setZoomerValue(zoomer.getValue());
                getSelectedSpace().repaint();
                getSelectedPane().getHorizontalScrollBar().setValue((int) Math.round(hPortion*hScale - (hVisible()/2)));
                getSelectedPane().getVerticalScrollBar().setValue((int) Math.round(vPortion*vScale - (vVisible()/2))); 
                getSelectedPane().addNotify();
                getSelectedPane().revalidate();
                getSelectedPane().setDoubleBuffered(true);
                getSelectedPane().getHorizontalScrollBar().revalidate();
                getSelectedPane().getVerticalScrollBar().revalidate();
                getSelectedSpace().repaint();
            }
        });
        
        
        
        
        
        /**and using a group layout, we add a new tab to our JFrame
                 * my original code was using buttons I'm just simplifying the code to make it                  .                */easier to read,that's why I'm using group layour     ,          
        GroupLayout groupLayout = new GroupLayout(frmMyWorld.getContentPane());
        groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 85, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                        .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 1335, GroupLayout.PREFERRED_SIZE))
                    .addGap(28))
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                        .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 624, GroupLayout.PREFERRED_SIZE)
                        .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 642, GroupLayout.PREFERRED_SIZE))
                    .addGap(18))
        );
        groupSettingManager(groupLayout);
        
        
        
    }

newTab() 函数是我们创建新标签时所做的

void newTab() {
        //We first create a new workspace with the given dimentions 
        Workspace workSpace = new Workspace(1295*256, 592*256);
//request focus so we can add key listeners
        workSpace.requestFocus();
        //Our workspace sits inside a scroll pane
        JScrollPane scrollPane = new JScrollPane(workSpace);
        numberOfTabbs++;
        //our scroll pane sits inside a tabbed pane
        tabbedPane.addTab("Workspace " + numberOfTabbs, scrollPane);
        tabbedPane.setSelectedIndex(numberOfTabbs-1);
        scrollPane.getHorizontalScrollBar().addMouseListener(new MouseListener(){
            @Override
            public void mousePressed(MouseEvent e) {
                isScrolling = true;
            }
            @Override
            public void mouseClicked(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}
        });
        scrollPane.getVerticalScrollBar().addMouseListener(new MouseListener(){
            @Override
            public void mousePressed(MouseEvent e) {
                isScrolling = true;
            }
            @Override
            public void mouseClicked(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}
        });
        
        
    }

您可能已经注意到,我们在新工作区创建后立即请求焦点,但是,这似乎并没有给它焦点

我试过将关键监听器添加到工作区,就像这样

public class Workspace extends JPanel implements KeyListener{
        //we keep every landmass that will appear in the workspace stored in this array
        public ArrayList<Node> protoLandmass = new ArrayList<Node>();
        
        private static Color backGroundColor;
        private int zoomerValue;
        private static double zoomFactor; 
        private static int width;
        private static int height;
        private static boolean zooming = false;

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        
        public Workspace(int w, int h) {
            eventHandlers();
            this.setPreferredSize(new Dimension(w,h));
            
            backGroundColor = new Color(0,120,255);
            this.setBackground(backGroundColor);
            zoomFactor = 1;
            width = w;
            height = h;
            zoomerValue = 1000;
            this.setFocusable(true);
                        //I've also tried to request focus here, that didn't work either
            //this.requestFocus();
            this.addKeyListener(this);
            //this.requestFocusInWindow();
            repaint();
        }

                ...

                @Override
        public void keyTyped(KeyEvent e) {
            ... 
        }
        @Override
        public void keyPressed(KeyEvent e) {
            ...
            }   
        }
        @Override
        public void keyReleased(KeyEvent e) {
            ...
        }

这里的关键监听器不起作用,即使我已经尝试在多个地方请求焦点

当我在这里创建事件时,鼠标监听器似乎起作用了:

private void eventHandlers() {
            this.addMouseListener(new MouseAdapter() {  
                @Override
                public void mousePressed(MouseEvent e) {
                        ...
                    repaint();
                }
                
                public void mouseClicked(MouseEvent e) {
                                ...
                }
                public void mouseReleased(MouseEvent e) {
                                ...
                }
                public void mouseExited(MouseEvent e) {
                                        ...
                    repaint();
                }
                public void mouseEntered(MouseEvent e) {
                    ...
                    repaint();
                }
            });
            
            this.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                        repaint();
                }
                public void mouseDragged(MouseEvent e) {
                    repaint();
                }
            
                public void mouseWheelMoved(MouseEvent e) {
                                       // this one doesn't work either
                        Cartographer.isScrolling = true;
                }
            });
                
                this.addKeyListener(new KeyAdapter(){

               @Override
        public void keyTyped(KeyEvent e) {
            ...
            
        }
                @override
        public void keyPressed(KeyEvent e) {
            ...
            }
                
                
            
        }
                @override
        public void keyReleased(KeyEvent e) {
            ... 
        }       
            
    }

我尝试在这里添加关键监听器,但它们也没有用。我从来没有尝试过同时在两个地方都有主要的听众,我只是展示他们去过的所有地方,让你更容易。

最小可重现示例:

  import java.awt.Color;  
    import java.awt.EventQueue;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTabbedPane;
    import javax.swing.GroupLayout;
    import javax.swing.GroupLayout.Alignment;
    import javax.swing.LayoutStyle.ComponentPlacement;
    import javax.swing.JSlider;
    import javax.swing.SwingConstants;
    import javax.swing.event.ChangeListener;
    import javax.swing.event.ChangeEvent;
    
    
    
    public class Cartographer {
    
        private final JFrame frmMyWorld = new JFrame();
        /**
         * set up our toolbar
         */
        double hPortion = 0;
        double vPortion = 0;
        
        
        //the space that will contain everything that is drawn
        private static JTabbedPane tabbedPane;
        private int numberOfTabbs;
        public static boolean isScrolling;
        private static JSlider zoomer;
        
        
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        Cartographer window = new Cartographer();
                        window.frmMyWorld.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * Create the application.
         */
        public Cartographer() { 
            initialize();
        }
    
        /**
         * Initialise the contents of the frame.
         */
        private void initialize() {
            
            frmMyWorld.setTitle("My World");
            frmMyWorld.setBounds(0, 0, 1450, 805);
            frmMyWorld.getContentPane().setBackground(new Color(100,100,100));
            frmMyWorld.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            tabbedPane = new JTabbedPane(JTabbedPane.TOP);
            newTab();
            isScrolling = true;
    
            /**
             * give everything its position in the window, we're using a group layout
             */
            zoomer = new JSlider();
            zoomer.setMinimum(-1000);
            zoomer.setMaximum(1000);
            zoomer.setValue(1000);
            zoomer.setOrientation(SwingConstants.VERTICAL);
            zoomer.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    if(isScrolling) {
                        hPortion = getHPortion();
                        vPortion = getVPortion();
                    }
                    isScrolling = false;
                    int hScale = (int) getSelectedPane().getHorizontalScrollBar().getMaximum();
                    int vScale = (int) getSelectedPane().getVerticalScrollBar().getMaximum();
                    getSelectedSpace().setZoomFactor(Math.pow(2, (double) zoomer.getValue()/1000 - 1));
                    getSelectedSpace().setZoomerValue(zoomer.getValue());
                    getSelectedSpace().repaint();
                    getSelectedPane().getHorizontalScrollBar().setValue((int) Math.round(hPortion*hScale - (hVisible()/2)));
                    getSelectedPane().getVerticalScrollBar().setValue((int) Math.round(vPortion*vScale - (vVisible()/2))); 
                    getSelectedPane().addNotify();
                    getSelectedPane().revalidate();
                    getSelectedPane().setDoubleBuffered(true);
                    getSelectedPane().getHorizontalScrollBar().revalidate();
                    getSelectedPane().getVerticalScrollBar().revalidate();
                    getSelectedSpace().repaint();
                }
            });
            
            
            
            
            
            
            GroupLayout groupLayout = new GroupLayout(frmMyWorld.getContentPane());
            groupLayout.setHorizontalGroup(
                groupLayout.createParallelGroup(Alignment.LEADING)
                    .addGroup(groupLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 85, GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                            .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 1335, GroupLayout.PREFERRED_SIZE))
                        .addGap(28))
            );
            groupLayout.setVerticalGroup(
                groupLayout.createParallelGroup(Alignment.LEADING)
                    .addGroup(groupLayout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                            .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 624, GroupLayout.PREFERRED_SIZE)
                            .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 642, GroupLayout.PREFERRED_SIZE))
                        .addGap(18))
            );
            groupSettingManager(groupLayout);
            
            
            
        }
        
    
    
        void groupSettingManager(GroupLayout groupLayout) {
                frmMyWorld.getContentPane().setLayout(groupLayout);
        }
    
    
        void newTab() {
            //We first create a new workspace with the given dimentions 
            Workspace workSpace = new Workspace(1295*4, 592*4);
            //we need to focus on this new workspace for key listeners to work
            //Our workspace sits inside a scroll pane
            JScrollPane scrollPane = new JScrollPane(workSpace);
            numberOfTabbs++;
            //our scroll pane sits inside a tabbed pane
            tabbedPane.addTab("Workspace " + numberOfTabbs, scrollPane);
            workSpace.requestFocus();
            tabbedPane.setSelectedIndex(numberOfTabbs-1);
            scrollPane.getHorizontalScrollBar().addMouseListener(new MouseListener(){
                @Override
                public void mousePressed(MouseEvent e) {
                    isScrolling = true;
                }
                @Override
                public void mouseClicked(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}
            });
            scrollPane.getVerticalScrollBar().addMouseListener(new MouseListener(){
                @Override
                public void mousePressed(MouseEvent e) {
                    isScrolling = true;
                }
                @Override
                public void mouseClicked(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}
            });
            
            
        }
        
        
        static Workspace getSelectedSpace() {
            return ((Workspace) ((JScrollPane) tabbedPane.getSelectedComponent()).getViewport().getView());
        }
        JScrollPane getSelectedPane() {
            return (JScrollPane) tabbedPane.getSelectedComponent();
        }
        Workspace getSpace(int i) {
            return ((Workspace) ((JScrollPane) tabbedPane.getComponent(i)).getViewport().getView());
        }
        JScrollPane getPane(int i) {
            return (JScrollPane) tabbedPane.getComponent(i);
        }
        
        
        
         static void setZoomerValue(int i) {
            if(-1000 <= i && i <= 1000)
                zoomer.setValue(i);
        }
        int getZoomerValue() {
            return zoomer.getValue();   
        }
        
        public double getHPortion() {
            int m = getSelectedPane().getHorizontalScrollBar().getMaximum();
            int v = getSelectedPane().getHorizontalScrollBar().getValue();
            double a = getSelectedPane().getHorizontalScrollBar().getVisibleAmount()/2;
            return (v + a)/m;
        }
        public double getVPortion() {
            int m = getSelectedPane().getVerticalScrollBar().getMaximum();
            int v = getSelectedPane().getVerticalScrollBar().getValue();
            double a = getSelectedPane().getVerticalScrollBar().getVisibleAmount()/2;
            return (v +a)/m;
        }
        public int hVisible() {
            return getSelectedPane().getHorizontalScrollBar().getVisibleAmount();
        }
        public int vVisible() {
            return getSelectedPane().getVerticalScrollBar().getVisibleAmount();
        }
    
    
    }

    import java.awt.Color; 
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.LayoutManager;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;

    import javax.swing.JPanel;

    public class Workspace extends JPanel implements KeyListener{
        //we keep every landmass that will appear in the workspace stored in this array
        
        private static Color backGroundColor;
        private static Color foreGroundColor;
        private int zoomerValue;
        private static double zoomFactor; 
        private static int width;
        private static int height;

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        
        public Workspace(int w, int h) {
            eventHandlers();
            this.setPreferredSize(new Dimension(w,h));
            
            backGroundColor = Color.BLACK;
            foreGroundColor = Color.WHITE;
            this.setBackground(backGroundColor);
            zoomFactor = 1;
            width = w;
            height = h;
            zoomerValue = 1000;
            this.setFocusable(true);
            this.requestFocus();
            this.addKeyListener(this);
            //this.requestFocusInWindow();
            repaint();
        }
        




        public Workspace(LayoutManager layout) {
            super(layout);
            
        }

        public Workspace(boolean isDoubleBuffered) {
            super(isDoubleBuffered);
            
        }

        public Workspace(LayoutManager layout, boolean isDoubleBuffered) {
            super(layout, isDoubleBuffered);
            
        }
        
        public double getZoomFactor() {
            return zoomFactor;
        }
        public void setZoomFactor(double z) {
            zoomFactor = z;
            repaint();
        }
        public void adjustZoomFactor(int z) {
            zoomFactor = Math.pow(2, z);
            repaint();
        }
        
        
        public int getZoomerValue() {
            return zoomerValue;
        }
        public void setZoomerValue(int i) {
            zoomerValue = i;
        }
        
        
        
        
        
        
        
        /**
         * Paint Function and supplement functions 
         */
        public void paint(Graphics g)
        {
            Graphics2D g2= (Graphics2D) g;
            zoom(g2);
            //a for loop to run the same function on each of the landmasses to draw them all    
            for(int i = 0; i < 35; i++)
                for(int j = Math.floorMod(i, 2); j < 16; j+=2) {
                    g2.setColor(foreGroundColor);
                    g2.fillRect(148*i, 148*j, 148, 148);
                    g2.setColor(Color.GREEN);
                    g2.drawString("(" + i + "," + j + ")",148*i+66,148*j+72);
                }
            this.setBackground(backGroundColor);
            
        }
        private void zoom(Graphics2D g) {
            //if(zooming) g.translate(-getMousePosition().x, -getMousePosition().y);
            g.scale(zoomFactor,zoomFactor);
            this.setPreferredSize(new Dimension((int) Math.round(width*zoomFactor), (int) Math.round(height*zoomFactor)));
            this.validate();
            //if(zooming) g.translate(getMousePosition().x, getMousePosition().y);

        }
        
        
        
        /**
         * Any events that occur within the workspace happen here
         */
        private void eventHandlers() {
            this.addMouseListener(new MouseAdapter() {  
                @Override
                public void mousePressed(MouseEvent e) {
                    foreGroundColor = Color.BLUE;
                    repaint();
                }
                
                public void mouseClicked(MouseEvent e) {
                    backGroundColor = Color.GRAY;
                    repaint();
                }
                public void mouseReleased(MouseEvent e) {
                    foreGroundColor = Color.WHITE;
                    repaint();
                }
                public void mouseExited(MouseEvent e) {
                    backGroundColor = Color.BLACK;
                    repaint();
                }
                public void mouseEntered(MouseEvent e) {
                    Cartographer.setZoomerValue(zoomerValue);
                    repaint();
                }
            });
            
            this.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                        repaint();
                }
                public void mouseDragged(MouseEvent e) {
                    repaint();
                }
            
                public void mouseWheelMoved(MouseEvent e) {
                        Cartographer.isScrolling = true;
                }
            });
            
            this.addKeyListener(new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    foreGroundColor = Color.RED;
                }
            });
            
            
        }
        
        
        public int mousePositionX() {
            return (int) Math.round(getMousePosition().x/zoomFactor);
        }
        public int mousePositionY() {
            return (int) Math.round(getMousePosition().y/zoomFactor);
        }


        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub
            
        }

        @Override
        public void keyPressed(KeyEvent e) {
            switch(e.getKeyCode()) {
            case 38 : if(zoomerValue < 1000) { zoomerValue+=5; Cartographer.setZoomerValue(zoomerValue);} 
                repaint();
            break;
            case 40 : if(zoomerValue > -1000) {zoomerValue-=5; Cartographer.setZoomerValue(zoomerValue);} 
                System.out.println(zoomerValue);
                repaint();
            break;
            default: repaint();
            }
                
                
            
        }

        @Override
        public void keyReleased(KeyEvent e) {
                
        }
        
        
        

}
java swing event-handling jpanel keylistener
1个回答
0
投票

因此,使用您的代码,我可以证明键绑定确实在嵌套组件内部起作用,这里的绑定位于 g 键上,表示“绿色”。按下该键时,组件的前景色变为绿色。

绑定:

private void eventHandlers() {
    
    // .......

    // add some key bindings to test that they work
    InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
    ActionMap actionMap = getActionMap();

    // when the g-key is pressed, the foreground color is set to green
    KeyStroke gDownKey = KeyStroke.getKeyStroke(KeyEvent.VK_G, 0, false);
    KeyStroke gUpKey = KeyStroke.getKeyStroke(KeyEvent.VK_G, 0, true);

    inputMap.put(gDownKey, "gDown");
    actionMap.put("gDown", new ForeGroundColorAction(Color.GREEN));

    inputMap.put(gUpKey, "gUp");
    actionMap.put("gUp", new ForeGroundColorAction(Color.WHITE));
}

private class ForeGroundColorAction extends AbstractAction {
    private Color color;

    public ForeGroundColorAction(Color color) {
        this.color = color;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        foreGroundColor = color;
        repaint();
    }
}

还有我的MRE演示程序:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.*;

public class Cartographer {
    private final JFrame frmMyWorld = new JFrame();
    double hPortion = 0;
    double vPortion = 0;
    private JTabbedPane tabbedPane;
    private int numberOfTabbs;
    public boolean isScrolling;
    private JSlider zoomer;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Cartographer window = new Cartographer();
                    window.frmMyWorld.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Cartographer() {
        initialize();
    }

    private void initialize() {
        frmMyWorld.setTitle("My World");
        frmMyWorld.setBounds(0, 0, 1450, 805);
        frmMyWorld.getContentPane().setBackground(new Color(100, 100, 100));
        frmMyWorld.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        newTab();
        isScrolling = true;
        zoomer = new JSlider();
        zoomer.setMinimum(-1000);
        zoomer.setMaximum(1000);
        zoomer.setValue(1000);
        zoomer.setOrientation(SwingConstants.VERTICAL);
        zoomer.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                if (isScrolling) {
                    hPortion = getHPortion();
                    vPortion = getVPortion();
                }
                isScrolling = false;
                int hScale = (int) getSelectedPane().getHorizontalScrollBar().getMaximum();
                int vScale = (int) getSelectedPane().getVerticalScrollBar().getMaximum();
                getSelectedSpace().setZoomFactor(Math.pow(2, (double) zoomer.getValue() / 1000 - 1));
                getSelectedSpace().setZoomerValue(zoomer.getValue());
                getSelectedSpace().repaint();
                getSelectedPane().getHorizontalScrollBar()
                        .setValue((int) Math.round(hPortion * hScale - (hVisible() / 2)));
                getSelectedPane().getVerticalScrollBar()
                        .setValue((int) Math.round(vPortion * vScale - (vVisible() / 2)));
                getSelectedPane().addNotify();
                getSelectedPane().revalidate();
                getSelectedPane().setDoubleBuffered(true);
                getSelectedPane().getHorizontalScrollBar().revalidate();
                getSelectedPane().getVerticalScrollBar().revalidate();
                getSelectedSpace().repaint();
            }
        });
        GroupLayout groupLayout = new GroupLayout(frmMyWorld.getContentPane());
        groupLayout.setHorizontalGroup(
                groupLayout.createParallelGroup(Alignment.LEADING)
                        .addGroup(groupLayout.createSequentialGroup()
                                .addContainerGap()
                                .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 85, GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                                        .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 1335,
                                                GroupLayout.PREFERRED_SIZE))
                                .addGap(28)));
        groupLayout.setVerticalGroup(
                groupLayout.createParallelGroup(Alignment.LEADING)
                        .addGroup(groupLayout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                                        .addComponent(zoomer, GroupLayout.PREFERRED_SIZE, 624,
                                                GroupLayout.PREFERRED_SIZE)
                                        .addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, 642,
                                                GroupLayout.PREFERRED_SIZE))
                                .addGap(18)));
        groupSettingManager(groupLayout);
    }

    void groupSettingManager(GroupLayout groupLayout) {
        frmMyWorld.getContentPane().setLayout(groupLayout);
    }

    void newTab() {
        // We first create a new workspace with the given dimentions
        Workspace workSpace = new Workspace(1295 * 4, 592 * 4, this);
        // we need to focus on this new workspace for key listeners to work
        // Our workspace sits inside a scroll pane
        JScrollPane scrollPane = new JScrollPane(workSpace);
        numberOfTabbs++;
        // our scroll pane sits inside a tabbed pane
        tabbedPane.addTab("Workspace " + numberOfTabbs, scrollPane);
        workSpace.requestFocus();
        tabbedPane.setSelectedIndex(numberOfTabbs - 1);
        scrollPane.getHorizontalScrollBar().addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                isScrolling = true;
            }

        });
        scrollPane.getVerticalScrollBar().addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                isScrolling = true;
            }
        });
    }

    Workspace getSelectedSpace() {
        return ((Workspace) ((JScrollPane) tabbedPane.getSelectedComponent()).getViewport().getView());
    }

    JScrollPane getSelectedPane() {
        return (JScrollPane) tabbedPane.getSelectedComponent();
    }

    Workspace getSpace(int i) {
        return ((Workspace) ((JScrollPane) tabbedPane.getComponent(i)).getViewport().getView());
    }

    JScrollPane getPane(int i) {
        return (JScrollPane) tabbedPane.getComponent(i);
    }

    void setZoomerValue(int i) {
        if (-1000 <= i && i <= 1000)
            zoomer.setValue(i);
    }

    int getZoomerValue() {
        return zoomer.getValue();
    }

    public double getHPortion() {
        int m = getSelectedPane().getHorizontalScrollBar().getMaximum();
        int v = getSelectedPane().getHorizontalScrollBar().getValue();
        double a = getSelectedPane().getHorizontalScrollBar().getVisibleAmount() / 2;
        return (v + a) / m;
    }

    public double getVPortion() {
        int m = getSelectedPane().getVerticalScrollBar().getMaximum();
        int v = getSelectedPane().getVerticalScrollBar().getValue();
        double a = getSelectedPane().getVerticalScrollBar().getVisibleAmount() / 2;
        return (v + a) / m;
    }

    public int hVisible() {
        return getSelectedPane().getHorizontalScrollBar().getVisibleAmount();
    }

    public int vVisible() {
        return getSelectedPane().getVerticalScrollBar().getVisibleAmount();
    }
}

class Workspace extends JPanel implements KeyListener {
    // we keep every landmass that will appear in the workspace stored in this array
    private Color backGroundColor;
    private Color foreGroundColor;
    private int zoomerValue;
    private Cartographer cartographer;
    private double zoomFactor;
    private int width;
    private int height;
    private static final long serialVersionUID = 1L;

    public Workspace(int w, int h, Cartographer cartographer) {
        this.cartographer = cartographer;
        eventHandlers();
        this.setPreferredSize(new Dimension(w, h));
        backGroundColor = Color.BLACK;
        foreGroundColor = Color.WHITE;
        this.setBackground(backGroundColor);
        zoomFactor = 1;
        width = w;
        height = h;
        zoomerValue = 1000;
        this.setFocusable(true);
        this.requestFocus();
        this.addKeyListener(this);
        setBackground(backGroundColor); // !!s
    }

    public Workspace(LayoutManager layout) {
        super(layout);
    }

    public Workspace(boolean isDoubleBuffered) {
        super(isDoubleBuffered);
    }

    public Workspace(LayoutManager layout, boolean isDoubleBuffered) {
        super(layout, isDoubleBuffered);
    }

    public double getZoomFactor() {
        return zoomFactor;
    }

    public void setZoomFactor(double z) {
        zoomFactor = z;
        repaint();
    }

    public void adjustZoomFactor(int z) {
        zoomFactor = Math.pow(2, z);
        repaint();
    }

    public int getZoomerValue() {
        return zoomerValue;
    }

    public void setZoomerValue(int i) {
        zoomerValue = i;
    }

    @Override // must override paintComponent, not paint
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // never forget this!

        // best to only scale a copy of the Graphics object so as not to break the painting chain
        Graphics2D g2 = (Graphics2D) g.create();
        zoom(g2);
        for (int i = 0; i < 35; i++) {
            for (int j = Math.floorMod(i, 2); j < 16; j += 2) {
                g2.setColor(foreGroundColor);
                g2.fillRect(148 * i, 148 * j, 148, 148);
                g2.setColor(Color.GREEN);
                g2.drawString("(" + i + "," + j + ")", 148 * i + 66, 148 * j + 72);
            }
        }
        g2.dispose();  // dispose of copy

        // this.setBackground(backGroundColor); // !! does not belong in painting method
    }

    private void zoom(Graphics2D g) {
        // if(zooming) g.translate(-getMousePosition().x, -getMousePosition().y);
        g.scale(zoomFactor, zoomFactor);
        this.setPreferredSize(
                new Dimension((int) Math.round(width * zoomFactor), (int) Math.round(height * zoomFactor)));
        this.validate();
        // if(zooming) g.translate(getMousePosition().x, getMousePosition().y);
    }

    /**
     * Any events that occur within the workspace happen here
     */
    private void eventHandlers() {
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                foreGroundColor = Color.BLUE;
                repaint();
            }

            public void mouseClicked(MouseEvent e) {
                backGroundColor = Color.GRAY;
                repaint();
            }

            public void mouseReleased(MouseEvent e) {
                foreGroundColor = Color.WHITE;
                repaint();
            }

            public void mouseExited(MouseEvent e) {
                backGroundColor = Color.BLACK;
                repaint();
            }

            public void mouseEntered(MouseEvent e) {
                cartographer.setZoomerValue(zoomerValue);
                repaint();
            }
        });
        this.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                repaint();
            }

            public void mouseDragged(MouseEvent e) {
                repaint();
            }

            public void mouseWheelMoved(MouseEvent e) {
                cartographer.isScrolling = true;
            }
        });
        this.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                foreGroundColor = Color.RED;
            }
        });

        // add some key bindings to test that they work
        InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = getActionMap();

        // when the g-key is pressed, the foreground color is set to green
        KeyStroke gDownKey = KeyStroke.getKeyStroke(KeyEvent.VK_G, 0, false);
        KeyStroke gUpKey = KeyStroke.getKeyStroke(KeyEvent.VK_G, 0, true);

        inputMap.put(gDownKey, "gDown");
        actionMap.put("gDown", new ForeGroundColorAction(Color.GREEN));

        inputMap.put(gUpKey, "gUp");
        actionMap.put("gUp", new ForeGroundColorAction(Color.WHITE));
    }

    private class ForeGroundColorAction extends AbstractAction {
        private Color color;

        public ForeGroundColorAction(Color color) {
            this.color = color;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            foreGroundColor = color;
            repaint();
        }
    }

    public int mousePositionX() {
        return (int) Math.round(getMousePosition().x / zoomFactor);
    }

    public int mousePositionY() {
        return (int) Math.round(getMousePosition().y / zoomFactor);
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case 38:
                if (zoomerValue < 1000) {
                    zoomerValue += 5;
                    cartographer.setZoomerValue(zoomerValue);
                }
                repaint();
                break;
            case 40:
                if (zoomerValue > -1000) {
                    zoomerValue -= 5;
                    cartographer.setZoomerValue(zoomerValue);
                }
                System.out.println(zoomerValue);
                repaint();
                break;
            default:
                repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}

注意我删除了许多静态修饰符。另外,你不应该在 paint 中绘制,而应该在 paintComponent 中绘制,并且不要忘记调用 super 的方法来进行内务绘制。此外,缩放通常应该在 JVM 提供的 Graphics 对象的副本上完成。

© www.soinside.com 2019 - 2024. All rights reserved.