Java Swing:使用线程改善游标响应 [英] Java Swing: Improving cursor response using Threads

查看:94
本文介绍了Java Swing:使用线程改善游标响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要加快将光标悬停在一堆矩形上的速度.随着矩形数量(或复杂度)的增加,迭代矩形的直接 linear 算法开始恶化.

I need to speed up the cursor response which is hovering over a bunch of rectangles. As the rectangles increase in number(or complexity), the straight forward linear algorithm of iterating over the rectangles starts to deteriorate.

此超链接显示线性搜索模型(记住要添加break关键字!!!)

This hyperlink shows a linear search model(remember to add the break keyword!!!)linear approach

为了清楚地说明我的意思,下面是具有两组矩形的JPanel的代码.第一组是y轴上的矩形列表,第二组是x轴上的矩形列表

To clearly show what I mean,below is code of a JPanel that has two groups of rectangles.The first group is a List of rectangles on the y-axis, the second group is a List of rectangles on the x-axis.

请记住,我的解决方案是我想到的最好的解决方案,即使用两个线程同时进行迭代.每个列表一个线程,一个用于x轴,另一个用于y轴.我放弃的次优解决方案(未显示代码)是在一个循环中存在一个循环.一个专门用于x轴矩形的循环,另一个专门用于y轴矩形的循环.通过contain()方法(假定内部循环专用于y轴矩形)对y轴矩形进行了处理,因为首先循环遍历所有x轴矩形会产生不必要的开销.

Keep in mind, that my solution is the best I could think of, of using Two threads to concurrently iterate; one thread per List,one for x-axis and other for y-axis. The sub-optimal solution that I abandoned(code not displayed) is where there was a loop within a loop.One loop dedicated for the x-axis rectangles and the other for y-axis rectangles.This,I deemed sub-optimal as searching for a y-axis rectangle through the contain() method (assuming the inner loop is dedicated for y-axis rectangles) imposed an undue overhead by looping over all x-axis rectangles first.

为了改善线性模型,我想到了这种线程方法来同时使用辅助线程.

To improve the linear model i thought of this threaded approach to simultaneously engage worker threads.

顺便说一句,我是Java新手,尤其是在多线程方面.

Btw, am a java novice,especially in multi-threading.

问题: 一个线程似乎干扰了另一个线程的性能.下面的算法是通过扩展Thread的两个包装器类实现的,这两个包装器类均具有在矩形上进行迭代的方法.如果注释掉另一个,则它们各自都可以很好地工作,即,每个都可以正常工作. >分别和 ,但是当两者同时启动时,会对性能产生影响.

Problem: One thread seems to disturb the performance of the other.The algorithm below is implemented by two wrapper classes extending Thread which both have a method of iterating over rectangles.They each both work excellently if the other is commented out,i.e each works well individually and separately ,but one takes a performance hit when both start at the same time.

如果我加入()一个线程,那难道不是恢复为线性模型的问题,因为矩形的复杂性越来越高,搜索算法效果不佳?

If I join() one thread,isn't that reverting to a linear model which is poor search algorithm as rectangles grow in complexity?

(复杂性不仅意味着水平和垂直,还包括对角的e.t.c矩形)?

(complexity means not only horizontal and vertical, but also diagonal e.t.c rectangles)?

public class FlyingSaucer extends JPanel {
    Rectangle2D rec;
    Rectangle2D rec1; 
    List<Rectangle2D> recList;
    List<Rectangle2D> recList2;

    Rectangle2D.Double mouseBoxx;  
    int f = 10;
    int g = 0;
    int s = 10;
    int y = 5;
    int z = 500;

    public FlyingSaucer(){

        //FlyingSaucer needs to quickly identify specific points over given areas
        //enclosed in rectangles.They use a 'divide and conquer' approach where 
        //different types of rectangles are first identified and a worker thread
        //assigned to each category

        mouseBoxx = new Rectangle.Double();
        recList = new ArrayList<>();
        recList2 = new ArrayList<>();

        for(int i = 0; i < 15; i++){
            rec = new Rectangle2D.Double(2+f,10+g,5,1000);       
            f +=50;
            recList.add(rec);                
        }
        f = 10;

        for(int i = 0; i < 20; i++){
            rec1 = new Rectangle2D.Double(2+y,10+s,1000,5);       
            s +=35;
            recList2.add(rec1);                
        }
        s = 10;
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame();
        FlyingSaucer fs = new FlyingSaucer();
        Laser laser = new Laser(fs);
        fs.addMouseMotionListener(laser);
        fs.addMouseListener(laser);
        frame.getContentPane().add(fs);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(700,700);
        frame.setVisible(true);     
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); 
        ((Graphics2D)g).setColor(Color.RED);
        int a = 10;
        int b = 10;

        for(int i = 0;i < recList.size();i++){               
           ((Graphics2D)g).draw(recList.get(i));
        }

        for(int i = 0;i < recList2.size();i++){               
           ((Graphics2D)g).draw(recList2.get(i));
        }
    }
}


class Laser implements MouseListener,MouseMotionListener{
    Rectangle2D.Double mouseBox;
    Rectangle2D.Double recx;
    Rectangle2D.Double recy;
    FlyingSaucer fs;
    public Laser(FlyingSaucer fs){
        this.fs = fs;
    }

    @Override public void mouseClicked (MouseEvent e) { }
    @Override public void mousePressed (MouseEvent e) { }
    @Override public void mouseReleased(MouseEvent e) { }
    @Override public void mouseEntered (MouseEvent e) { }
    @Override public void mouseExited  (MouseEvent e) { }
    @Override public void mouseDragged (MouseEvent e) { }

    @Override
    public void mouseMoved(MouseEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                double x = e.getX();
                double y = e.getY();

                mouseBox = fs.mouseBoxx;
                mouseBox = new Rectangle2D.Double(x-5,y-5,10,10);

                Graphics g = fs.getGraphics();
                ((Graphics2D)g).setColor(Color.BLACK);
                ((Graphics2D)g).draw(mouseBox);

                //thread one for horizontal rectangles
                HorizontalBuffer hb = new HorizontalBuffer(fs,e);
                hb.start();

                //thread two for vertical rectangles
                VerticalBuffer vb = new VerticalBuffer(fs,e);
                vb.start();

                fs.repaint();
                g.dispose();
        }});
    }

    class HorizontalBuffer extends Thread{
        FlyingSaucer fs;
        MouseEvent e;
        List<Rectangle2D> recX;

        public HorizontalBuffer(FlyingSaucer fs,MouseEvent e){
            this.fs = fs;
            this.e = e;
        }

        public void run() {
            recX = fs.recList;
            Iterator <Rectangle2D> recs = recX.iterator();  
            int v = 1;
            while(recs.hasNext()){
                recx = (Rectangle2D.Double) recs.next();
                if(recx.contains(e.getPoint())){
                    System.out.println("X rectangle detected.."+v);
                     fs.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                    break;
                }
                else {fs.setCursor(Cursor.getDefaultCursor());}

                v++;
            }
        }
    }

    class VerticalBuffer extends Thread{
        FlyingSaucer fs;
        MouseEvent e;
        //List<Rectangle2D> recX;
        List<Rectangle2D> recY;

        public VerticalBuffer(FlyingSaucer fs,MouseEvent e){
            this.fs = fs;
            this.e = e;
        }

        public void run(){
            recY = fs.recList2;
            Iterator <Rectangle2D> recs = recY.iterator();  
            int v = 1;
            while(recs.hasNext()){
                recy = (Rectangle2D.Double) recs.next();
                if(recy.contains(e.getPoint())){
                    System.out.println("Y rectangle detected.."+v);
                    fs.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                    break;
                }
                else {fs.setCursor(Cursor.getDefaultCursor());}

                v++;
            }
        }
    }
}

推荐答案

您的FlyingSaucer类不是线程安全的,但是您是从Horizo​​ntalBuffer和VerticalBuffer这两个不同的线程访问它的.这可能会引起问题:例如,当Horizo​​ntalBuffer尝试获取FlyingSaucer reclist时,它可能会变为null并引发异常.由于不同步的访问,也可能会出现其他问题.这不是最容易调试的事情:例如,除非您正在监视控制台,否则您将不知道该异常,因为一个线程中的异常不会终止多线程程序.

Your FlyingSaucer class is not thread safe, but you are accessing it from two different threads, HorizontalBuffer and VerticalBuffer. This is likely to cause problems: for example, when HorizontalBuffer tries to get the FlyingSaucer reclist, it might be getting null and throwing an exception. Other problems could also occur due to unsynchronized access. This isn't the easiest thing to debug: for example, you won't know about the exception unless you are watching the console, since an exception in one thread doesn't terminate a multithreaded program.

通过适当地同步对它的访问,使FlyingSaucer线程安全,可以解决此特定的访问同步问题.但是,还可能存在其他问题.要使多线程应用程序正常运行并非易事,对于您所说的Java新手来说,它可能不是最佳方法.

You could fix this particular access synchronization problem by making FlyingSaucer thread safe, by properly synchronizing access to it. However, there may also be other problems; getting a multithreaded application working properly is not simple, and might not be the best approach for a Java novice, which you say you are.

正如其他人在评论中指出的那样,最好的解决方案可能不是多线程.我建议您在单线程解决方案中发布一个新问题,并询问如何加快速度.您可以在该问题中提及多线程,但我建议也对其他解决方案开放.

As noted by others in the comments, it's likely that the best solution is not multithreading. I'd suggest posting a new question with your single threaded solution and asking how to speed it up. You can mention multithreading in that question, but I'd recommend being open to other solutions as well.

这篇关于Java Swing:使用线程改善游标响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆