sashaaero
sashaaero

Reputation: 2888

How to write some 'pause' in method?

Here I have a method

public static Color pickColor(){
    final aero.colorpicker.Frame frame = new aero.colorpicker.Frame();
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (!frame.isSelected()) {
                try {
                    Thread.currentThread().sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
    return frame.getColorPicked();
}

isSelected() is flag that makes us know that user CHOOSED the color he want.

The problem is - if I use it like Color c = pickColor(); in c will write default (black) color of aero.colorpicker.Frame class.
I need pause here, which will wait for select.

package aero.colorpicker;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Aero on 28.12.2014.
 */
public class Frame extends JFrame {
    //MAINFIELD
    private Color colorPicked = Color.black;
    private boolean selected = false;

    //GUIFIELDS
    private JPanel rightPanel;
    private JLabel R;
    private JLabel G;
    private JLabel B;
    private JTextField RData;
    private JTextField GData;
    private JTextField BData;
    private JPanel RPanel;
    private JPanel GPanel;
    private JPanel BPanel;
    private ColorPanel colorPanel;
    private JButton pick;
    private BufferedImage colors;
    private JLabel imageLabel;

    public Frame(){
        initFrame();
        setVisible(true);
    }

    private void initComponents(){
        rightPanel = new JPanel();
        R = new JLabel("R");
        G = new JLabel("G");
        B = new JLabel("B");
        RData = new JTextField();
        GData = new JTextField();
        BData = new JTextField();
        RPanel = new JPanel();
        GPanel = new JPanel();
        BPanel = new JPanel();
        colorPanel = new ColorPanel();
        pick = new JButton("Pick");
    }

    private void addListeners(){
        RData.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getRed();
                colorPanel.repaint();
            }
        });
        GData.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getGreen();
                colorPanel.repaint();
            }
        });
        BData.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getBlue();
                colorPanel.repaint();
            }
        });
        pick.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                getRed();
                getBlue();
                getGreen();
                Frame.this.setVisible(false);
            }
        });
        imageLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                int x, y;
                x = e.getX();
                y = e.getY();
                setColorPicked(new Color(colors.getRGB(x, y)));
                colorPanel.repaint();
                RData.setText(Integer.toString(getColorPicked().getRed()));
                BData.setText(Integer.toString(getColorPicked().getBlue()));
                GData.setText(Integer.toString(getColorPicked().getGreen()));
            }
        });
    }

    private void getRed(){
        int r;
        try {
            r = Integer.parseInt(RData.getText());
        }catch (NumberFormatException nfe){
            RData.setText("0");
            r = 0;
        }
        setColorPicked(r, getColorPicked().getGreen(), getColorPicked().getBlue());
    }

    private void getGreen(){
        int g;
        try {
            g = Integer.parseInt(GData.getText());
        }catch (NumberFormatException nfe){
            GData.setText("0");
            g = 0;
        }
        setColorPicked(getColorPicked().getRed(), g, getColorPicked().getBlue());
    }

    private void getBlue(){
        int b;
        try {
            b = Integer.parseInt(BData.getText());
        }catch (NumberFormatException nfe){
            BData.setText("0");
            b = 0;
        }
        setColorPicked(getColorPicked().getRed(), getColorPicked().getGreen(), b);
    }

    private void initFrame(){
        this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        this.setLayout(new BorderLayout());
        this.setSize(369, 194);
        this.setTitle("Color picker");
        this.setResizable(false);
        initComponents();
        InputStream input = Frame.class.getClassLoader().getResourceAsStream("colorGradient.jpg");
        try {
            colors = ImageIO.read(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
        imageLabel = new JLabel(new ImageIcon(colors));
        this.add(imageLabel, BorderLayout.CENTER);
        rightPanel.setLayout(new GridLayout(5, 1));
        RPanel.setLayout(new GridLayout(1, 2));
        GPanel.setLayout(new GridLayout(1, 2));
        BPanel.setLayout(new GridLayout(1, 2));
        RPanel.add(R);
        RPanel.add(RData);
        GPanel.add(G);
        GPanel.add(GData);
        BPanel.add(B);
        BPanel.add(BData);
        rightPanel.add(RPanel);
        rightPanel.add(GPanel);
        rightPanel.add(BPanel);
        rightPanel.add(colorPanel);
        rightPanel.add(pick);
        this.add(rightPanel, BorderLayout.EAST);
        this.repaint();
        addListeners();
    }

    public Color getColorPicked() {
        return colorPicked;
    }

    private void setColorPicked(Color colorPicked) {
        this.colorPicked = colorPicked;
    }

    private void setColorPicked(int r, int g, int b){
        this.colorPicked = new Color(r, g, b);
    }

    private void setSelected(){
        selected = true;
    }

    public boolean isSelected(){
        return selected;
    }

    private class ColorPanel extends JPanel{
        public void paintComponent(Graphics g){
            g.setColor(colorPicked);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }
}

Upvotes: 0

Views: 97

Answers (1)

sprinter
sprinter

Reputation: 27946

Your issue here is that your method pickColor creates the thread that waits for a colour to be picked, starts it and then exits. In other words pickColor isn't waiting for the thread to complete. The thread itself does nothing when it does complete.

One solution would be to wait until the thread completes before exiting the method. That would still be poor design, however. It is possible (in fact, likely) that you are calling pickColor within the thread processing UI events (i.e. the dispatch thread) which will make the UI unresponsive. It also uses a unnecessary busy wait.

If this is what you want to do then you'll need to understand how to create a new event queue. You also need to understand how to use semaphores to block the thread. I'll provide the code here but I wouldn't recommend dumping it into your application without understanding what you are doing. This is designed to be a subclass of your dialog class so that the method used to close the dialog can be overwritten to notify the blocked thread.

For the method that shows the colour picking dialog:

public synchronized Color pickColor() {
    // code to create and show the dialog
    EventQueue tempEventQueue = new EventQueue();
    Toolkit.getDefaultToolkit().getSystemEventQueue().push(tempEventQueue);
    try {
        wait();
    } catch (InterruptedException ex) {
        // stop waiting on interrupt
    } finally {
        tempEventQueue.pop();
    }
    // return colour from dialog
}

For the method that is called when the user closes the dialog:

public synchronized void closeChooser() {
    notifyAll();
    super.closeChooser(); // or whatever it's called
}

The correct solution is to have two methods: one to open the colour pick dialog and then a second which is called when the dialog closes. I don't know what capabilities aero.colorpicker.Frame has but if it doesn't provide this then you could subclass it and override whatever method is called when the user accepts or cancels.

Upvotes: 2

Related Questions