Program Not Accessing Method Paintcomponent() of Extended Jpanel Class

Program not accessing method paintComponent() of extended JPanel class

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://stackoverflow.com/a/12228640/230513
* @see https://stackoverflow.com/a/7935040/230513
*/
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://stackoverflow.com/q/5830533/230513
* @see https://stackoverflow.com/a/3106550/230513
*/
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();
}
});
}
}

paintComponent is not drawing in the entire JPanel

Don't override getX() and getY() of the Segment class.

Those are methods of all Swing components. They get the current location of the component within the parent container.

Use different method names to control the location of the painting of your snake. Since your variable names are xPos and yPos maybe use getXPos() and getYPos().

So what happens is that the snake is drawn at xPos/yPos relative to the Segment panel and the Segment panel is also drawn at xPos/yPos relative to its parent container.

repaint() method not calling paintComponent

There are several problems with the posted code:

    frame.getContentPane().setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT));
...
frame.add(buttonPanel);
frame.add(arrPanel);

and

    bubbleSort.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT));
...
arrPanel.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT));
arrPanel.add(bubbleSort);

You set 3 different components to the same size. They can't all be the same size, since the content pane of the frame contains multiple components.

Don't keep setting the preferred size of components. It is the responsibility of each component to determine its own preferred size.

With components like buttons, if you want the button bigger, you can use the setMargins(...) method.

When doing custom painting, you would override the getPreferredSize() of the class, since your custom painting code knows best what the size should be.

static JPanel buttonPanel = new JPanel();
static JPanel arrPanel = new JPanel();
static JButton bubbleButton;
static JButton insertionButton;
static JButton selectionButton;
static Bubble bubbleSort;
static Insertion insertSort;
static Selection selectionSort;

Don't use static variable everywhere. This indicates improper design.

public static void initializeVars() {

Again, don't use static methods. Also improper design.

You need to create a class with instance variables and method that can access these instance variables.

graphics2d.fillRect(0, 0, AlgVisualiser.CONTENT_WIDTH, AlgVisualiser.CONTENT_HEIGHT);

Don't access variable from another class when doing painting. Instead you would use the getWidth() and getHeight() methods to determine the current size of the component so you can fil in the background of the panel.

    AlgVisualiser.frame.revalidate();
AlgVisualiser.frame.repaint();

Don't repaint the entire frame. You are only changing your custom component you you only need to repaint the component, not the entire frame. There is also no need for the reavalidate(). The revalidate() method is used to invoke the layout manager. Your are not adding or removing components from the panel.

the program just displays the array once the panel is made visible, showing the already sorted array.

Now the hard part.

The repaint() method just adds a paint request to the RepaintManager. The RepaintManager will then consolidate requests and add a paint request to the Event Dispatch Thread (EDT) which will repaint the frame.

The problem is your looping code executes so fast that you don't see the individual steps. So you need to use a Thread.sleep(...) so slow down processing to give the GUI a chance to paint each step.

Now you have another problem. If you use Thread.sleep() on the EDT, the GUI still can't repaint() itself until the loop is finished executing.

So you need to execute the soring code on a separate Thread. Then you can tell the sorting Thread to sleep and tell the GUI to repaint itself. One way to do this is to use a SwingWorker.

Read the section from the Swing tutorial on Concurrency for more information on the EDT and the SwingWorker.

How to call my paintComponent() method in another class

A paintComponent (better defined with @Override to detect typos) is automatically called during (re)paints of the GUI. So they are event driven, reacting. It is not intended to be called straight. Instead use one of the JComponent's repaint* methods, either on the DrawPicture variable, or on the entire JFrame (Windows).

public class DrawPicture extends JPanel {

private Image testItOut;

// Access for setting an other image.
public void setImage(Image testItOut) {
this.testItOut = testItOut;
}

public Image getImage() {
return testItOut;
}

public DrawPicture() {
try {
File a = new File("C:\\Users\\km\\Pictures\\Cards\\red_back.png");
testItOut = ImageIO.read(a);
} catch(IOException e) {
e.printStackTrace();
}
}

@Override
public void paintComponent(Graphics g) {
if (testItOut != null) {
g.drawImage(testItOut, 50, 300, this);
}
}
}

For instance:

b5.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
otaku.repaint(50L); // Repaint after 50 ms.
}
});

This can be shortened with lambdas as:

b5.addActionListener(e -> {
otaku.repaint(50L); // Repaint after 50 ms.
});

or even

b5.addActionListener(e -> otaku.repaint(50L));

A bit more realistic:

b5.addActionListener(e ->
SwingUtilities.invokeLater(() -> {
File imgFile = new File("C:\\Users\\km\\Pictures\\Cards\\green_back.png");
Image img = ImageIO.read(imgFile);
otaku.setImage(img);
otaku.repaint(50L);
}));

invokeLater makes the GUI behave more responsive when the code of the actionPerformed would take longer (it does not block during the button press).

paintComponent() not being called

It's no wonder that paintComponent is not called, because Canvas has no implementation of paintComponent which you can override. With a canvas you have to overwrite paint for your purposes. In your code you use both a JPanel and a Canvas, which is not necessary at all. Use either of the two.

The following is an example with a Canvas:

import java.awt.*;
import javax.swing.*;

public class ScreenSaver extends Canvas{
public static void main(String[] args) {
JFrame window = new JFrame("Screensaver");
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setResizable(false);

ScreenSaver canvas = new ScreenSaver();
canvas.setPreferredSize(new Dimension(1600, 900));
canvas.setBackground(Color.BLACK);

window.add(canvas);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}

@Override
public void paint(Graphics g){
g.setColor(Color.GREEN);
g.fillOval(100, 100, 100, 100);
}
}

The annotation Override above the method to be overwritten ensures that the compiler can issue a warning message if the overwritten method does not exist or there is a typo. I hope this helps you further.

JPanel gets paintComponent gets called when child is entered

This seems to be a design choice of Nimbus.

If you inspect the result of JTextField#isOpaque, it returns false (making it transparent). This means that when ever the component is repainted, the parent container must first be repainted as well.

The JTextField is triggering a repaint each time the caret is updated (blinks on and off)

The reason why your first JTextField doesn't cause a repaint on the Tester is because it's sitting inside a opaque container, so only it's immediate parent container will be repainted.

Try making the JTextField opaque (t2.setOpaque(true);) and see what happens



Related Topics



Leave a reply



Submit