Program not accessing method paintComponent() of extended JPanel class
Asked Answered
A

1

6

This is the JFrame

package client.connection;

import java.awt.Dimension;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.swing.JFrame;


class DrawFrameRemoteControl extends JFrame
{
    private DrawPanelRemoteControl imagePanel;
    private ClientRemoteControlConnection clientRemoteControlConnection;
    private ObjectInputStream clientInputStream;
    private ObjectOutputStream clientOutputStream;
    private Dimension imageDimension;
    private Dimension serverDimension;

    public DrawFrameRemoteControl(Dimension imageDimension,ClientRemoteControlConnection clientRemoteControlConnection,ObjectInputStream clientInputStream,ObjectOutputStream clientOutputStream,Dimension serverDimension)
    {
        super("Remote Desktop Control");

        this.clientRemoteControlConnection=clientRemoteControlConnection;
        this.clientInputStream=clientInputStream;
        this.clientOutputStream=clientOutputStream;
        this.imageDimension=imageDimension;
        this.serverDimension=serverDimension;

        imagePanel=new DrawPanelRemoteControl(imageDimension);
        add(imagePanel);


        setSize(imageDimension.width,imageDimension.height);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        setLocationRelativeTo(null);
    }

    void drawNewImageGrayscale(byte[] array)
    {
        imagePanel.setNewImageGrayscale(array);
        imagePanel.repaint();
    }
}

And this is the extended JPanel class-

package client.connection;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.MemoryImageSource;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

class DrawPanelRemoteControl extends JPanel
{
    private byte[] byteArray=null;
    private Image image;
    private JLabel imageLabel=new JLabel();
    private Dimension imageDimension;

    public DrawPanelRemoteControl(Dimension imageDimension)
    {
        this.imageDimension=imageDimension;
        add(imageLabel);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        System.out.println(".");
        if(byteArray!=null)
        {
            image=getGrayscaleImageFromArray(byteArray,imageDimension.width,imageDimension.height);
            imageLabel.setIcon(new ImageIcon(image));
        }
    }

    private Image getGrayscaleImageFromArray(byte[] buffer, int width, int height)
    {
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
        int[] nBits = { 8 };
        ColorModel cm = new ComponentColorModel(cs, nBits, false, true,Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        SampleModel sm = cm.createCompatibleSampleModel(width, height);
        DataBufferByte db = new DataBufferByte(buffer, width * height);
        WritableRaster raster = Raster.createWritableRaster(sm, db, null);
        BufferedImage result = new BufferedImage(cm, raster, false, null);
        return result;
    }

    void setNewImageGrayscale(byte[] array)
    {
        this.byteArray=array;
        this.intArray=null;
    }
}

I have tried debugging the code, even though imagePanel.repaint() is being executed many times, the program never reaches the paintComponent() method of DrawPanelRemoteControl class.

Can anybody give me any idea why this might be happening? Has it got anything to do with the imageDimension object?

Additional Information : In main() method, a DrawFrameRemoteControl object is created and it's drawNewImageGrayscale(byte[] arr) method is being updated from main() every second.

Appliance answered 1/9, 2012 at 8:29 Comment(4)
can you please post your main method.Glib
I tried your code its working fine ..., may be there is some other issue..Glib
never-ever change the state of the component in paintComponent (here indirectly by setting the icon of a child) nor do any potentially long tasks (loading an image)Cereal
@Cereal I did as you mentioned. But it seems like the main problem is that when a DrawFrameRemoteControl object is created from main() it works fine, but when a DrawFrameRemoteControl is created from another JFrame object, it's not initializing correctly(The file menu is not being shown, the background is showing white, where normally it's gray and the cross button is not working, when i click it nothing happens)Appliance
U
6

It's not clear why you're passing around byte[], but it looks like you want to update a component's Icon with a gray thumbnail. The example below creates grayscale icons from existing sample icons and uses setIcon() to do the update. A similar approach works with any Image. See also this example that suggests ColorConvertOp, and this example that updates whole components rather than icons.

Gray Icons Aqua

Gray Icons Nimbus

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import javax.swing.UIManager;

/**
 * @see https://mcmap.net/q/1014434/-program-not-accessing-method-paintcomponent-of-extended-jpanel-class
 * @see https://mcmap.net/q/1020763/-swing-timer-doesn-39-t-work-properly-closed
 */
public class GrayIcons extends JPanel {

    private List<Icon> list = new ArrayList<Icon>();
    private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
    private Timer timer = new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            update();
        }
    });

    public GrayIcons() {
        this.setLayout(new GridLayout(1, 0));
        list.add(getGray(UIManager.getIcon("OptionPane.errorIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.informationIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.warningIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.questionIcon")));
        for (Icon icon : list) {
            JToggleButton jtb = new JToggleButton(icon);
            buttons.add(jtb);
            this.add(jtb);
        }
        timer.start();
    }

    private void update() {
        Collections.shuffle(list);
        int index = 0;
        for (JToggleButton b : buttons) {
            b.setIcon(list.get(index++));
        }
    }

    /**
     * @see https://mcmap.net/q/464783/-how-can-i-convert-an-icon-to-an-image/230513
     * @see https://mcmap.net/q/1020762/-how-to-use-type_byte_gray-to-efficiently-create-a-grayscale-bufferedimage-using-awt
     */
    private Icon getGray(Icon icon) {
        final int w = icon.getIconWidth();
        final int h = icon.getIconHeight();
        GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gd.getDefaultConfiguration();
        BufferedImage image = gc.createCompatibleImage(w, h);
        Graphics2D g2d = image.createGraphics();
        g2d.setPaint(new Color(0x00f0f0f0));
        g2d.fillRect(0, 0, w, h);
        icon.paintIcon(null, g2d, 0, 0);
        BufferedImage gray = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
        ColorConvertOp op = new ColorConvertOp(
            image.getColorModel().getColorSpace(),
            gray.getColorModel().getColorSpace(), null);
        op.filter(image, gray);
        return new ImageIcon(gray);
    }

    private void display() {
        JFrame f = new JFrame("GrayIcons");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GrayIcons().display();
            }
        });
    }
}
Undecided answered 1/9, 2012 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.