Extends JPanel painting problem
Hello, sorry if this is in the wrong Forum Section but this seemed like the best place!
My problem is that I am currently designing a GUI that can display a Binary Search Tree (BST) from user entered data, I have the code nearly all working apart from the painting aspect of it. So I can enter all the data and everything into the BST fine but when it comes to painting there is problems for example when I first run the program and enter a value I want to displayed when I hit the add button which is suppose to draw a circle with the entered value inside it the circle and number will flash up and then disappear, I don't understand this as when I print out the BST using methods the value is definitely there etc. And if I add it again it will stay up and not flash away, it only seems to happen on the first circle so any others I add after that stay first time. Another problem is that if I either resize or navigate away from the GUI the BST that is displayed will vanish, again it's still stored but the painted BST will disappear. I think it may be because I haven't implemented the paintComponent method right or some problem with the area I paint on.
Below is some of the code that is relevant, if any more code or information is needed on this project to give a fuller picture I can put more up. Any help or advice or links on this matter would be so much help and I'd be very grateful! Thanks so much in advance! :)
Code :
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
public class PaintArea extends JPanel
{
public static void main(String args[])
{
Runnable r;
r = new Runnable()
{
public void run()
{
new PaintArea().startGUI();
}
};
SwingUtilities.invokeLater(r);
}
public static void startGUI()
{
...
//Create the painting area
paintarea = new PaintArea();
paintarea.setPreferredSize(new Dimension(480, 400));
scrollpane = new JScrollPane(paintarea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
frame.add(scrollpane, BorderLayout.CENTER);
...
// create the add button
add = new JButton();
add.setText("Add...");
// add actionListener to the add button
add.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
int i = Integer.parseInt(textField.getText());
binarySearchTree.insert(i);
double x = binarySearchTree.getX(binarySearchTree.getNode(i)); \\ Location in
double y = binarySearchTree.getY(binarySearchTree.getNode(i)); \\ BST
String LorR = binarySearchTree.getLorR(binarySearchTree.getNode(i));
\\ Determine if it's a right or left node
addcircle(paintarea, textField.getText(), x, y, LorR);
statusField.setText(textField.getText() + " : Added to Binary Search Tree" + "\t" +
"Items in search tree : " + binarySearchTree.count());
textField.setText("");
textField.requestFocusInWindow();
}
catch(NumberFormatException er)
{
statusField.setText("No valid number to add" + "\t\t" +
"Items in search tree : " + binarySearchTree.count());
textField.setText("");
textField.requestFocusInWindow();
}
}
});
// add the button to the bottom bar
buttonbar.add(add);
...
} // end startGUI
public static void addcircle(PaintArea p, String i, double x, double y, String LorR)
{
Graphics g = p.getGraphics();
int offsetx = p.getWidth()/2;
int valuex = (int) (p.getWidth()/4.5);
int offsety = 20;
int valuey = p.getHeight()/8;
int circle = 20;
double nodex = x;
double nodey = y;
int postionx = offsetx + (int) (nodex * valuex); \\ Used to declare X location of node
int postiony = (int) (nodey * valuey) + offsety; \\ Used to declare Y location of node
g.setColor(new Color(127, 255, 0));
g.fillOval(postionx, postiony, circle, circle);
g.setColor(Color.black);
g.drawOval(postionx, postiony, circle, circle);
if(LorR == "Left") \\ Used to draw a line to the node
{
double prex = x + 1/(Math.pow(2.0, y-1));
double prey = nodey - 1;
int prepostionx = offsetx + (int) (prex * valuex);
int prepostiony = (int) (prey * valuey) + offsety;
g.drawLine(postionx + 10, postiony, prepostionx + 10, prepostiony + 20);
}
else if (LorR == "Right")
{
double prex = x - 1/(Math.pow(2.0, y-1));
double prey = nodey - 1;
int prepostionx = offsetx + (int) (prex * valuex);
int prepostiony = (int) (prey * valuey) + offsety;
g.drawLine(postionx + 10, postiony, prepostionx + 10, prepostiony + 20);
}
// put in numbers
g.drawString(i, postionx + 3, postiony + 15);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
} // end class
Re: Extends JPanel painting problem
Never never use getGraphics on a Component in client code. Learn the correct way to perform custom painting here:
http://download.oracle.com/docs/cd/E...ing/index.html
Re: Extends JPanel painting problem
Thank you! So what I should be doing is making PaintArea extends JPanel its own class and leaving the other class as the GUI class? That link was very helpful thanks!
Re: Extends JPanel painting problem
Yup, custom painting is best done in an extended JPanel or JComponent.
Another word of advice: if laying out the custom drawing is processor intensive and/or time consuming, draw to a BufferdImage, call repaint() when done, and, in the paintComponent override, only drawImage(image, 0, 0, this);
Attempting lengthy computation inside any painting method is likely to lead to flicker and jitter.
db
edit Another way to display an image is as an Icon (usually ImageIcon) in a JLabel. No need to perform custom painting at all! You can probably create your own Icon implementation to do the drawing you require, and return appropriate width and height. Might be easier than going the custom painting route.