I am working on a little menu program with clickable buttons and an image that changes based on button clicks. If I click a button I get a shadow of the button at the bottom where I change the JLabel text. I cannot figure it out for the life of me. Any advice would be greatly appreciated. Visuals below...thanks
public class SampleGUI
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
System.out.println("Created GUI on EDT? " +
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Robert's VICI Prototype");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel
{
// Fields
Image imageDisplayed;
JLabel status;
// Methods
public MyPanel()
{
setBorder(BorderFactory.createLineBorder(Color.BLACK));
setLayout(null);
JLabel title = new JLabel("CS380 TEAM 5 VICI Prototype");
title.setFont(new Font("Tahoma", Font.BOLD, 20));
title.setBounds(425, 10, 400, 40);
add(title);
status = new JLabel("Please click an option above.");
status.setFont(new Font("Tahoma", Font.BOLD, 14));
status.setBounds(425, 740, 400, 40);
add(status);
JButton choice1 = new JButton("Search Class");
choice1.setBounds(50, 50, 150, 40);
add(choice1);
JButton choice2 = new JButton("Add Class");
choice2.setBounds(225, 50, 150, 40);
add(choice2);
JButton choice3 = new JButton("Drop Class");
choice3.setBounds(400, 50, 150, 40);
add(choice3);
JButton choice4 = new JButton("Verify Reg Hold");
choice4.setBounds(575, 50, 150, 40);
add(choice4);
JButton choice5 = new JButton("Verify Reg Date");
choice5.setBounds(750, 50, 150, 40);
add(choice5);
JButton choice6 = new JButton("Schedule Advisor");
choice6.setBounds(925, 50, 150, 40);
add(choice6);
choice6.addActionListener(
new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Schedule Advisor button pressed.");
status.setText("Choose a date.");
imageDisplayed = new ImageIcon("C:\\Temp\\sa01.jpg").getImage();
}
});
JButton exit = new JButton("EXIT");
exit.setBounds(940, 750, 150, 40);
add(exit);
exit.addActionListener(
new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
imageDisplayed = new ImageIcon("C:\\Temp\\main.jpg").getImage();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(1100, 800);
}
#Override
public void paintComponent(Graphics g)
{
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
}
You've broken the paint chain...
#Override
public void paintComponent(Graphics g)
{
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
The first thing you should be calling is super.paintComponent(g)
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
The Graphics context is shared resource, meaning that the Graphics context you get has also been used to paint the other components that have also been painted. One of the jobs of paintComponent is to clear the Graphics context ready for the component to be painted (fill the background)
See Painting in AWT and Swing and Performing Custom Painting for more details
You should, also, avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify. See Why is it frowned upon to use a null layout in SWING? for more details...
Before you go all defensive over getting your screen laid out just nicely, you shouldn't be doing it this way. You controls should be laid out on separate containers (using appropriate layout managers) and you "drawing surface" should be it's own component. See Laying Out Components Within a Container for more details...
If you're still not convicned, take a look at Why setting setPreferredSize() on JFrame is bad? and java expandable JDialog for examples of differences between Mac and Windows
Related
This question is an extension of java- repaint() method is misbehaving?
(Reading it, is optional)
I am working on a Music Player
I am using a JSlider as seek bar and using a JLabel to draw text on screen, such as song name.
I am new to Graphics2D
Here's the minimized code:
public class JSliderDemo extends JFrame
{
JLabel label;
JSlider seek = new JSlider();
int y = 10;
public JSliderDemo()
{
setSize(400, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
createWindow();
setVisible(true);
startThread();
}
public void createWindow()
{
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(true);
panel.setBackground(Color.BLUE);
panel.setBorder(new LineBorder(Color.YELLOW));
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
label = new Component();
label.setSize(300, 300);
createSlider();
layeredPane.add(seek, new Integer(50));
layeredPane.add(label, new Integer(100));
panel.add(layeredPane);
add(panel);
}
protected void createSlider()
{
seek.setUI(new SeekBar(seek, 300, 10, new Dimension(20, 20), 5,
Color.DARK_GRAY, Color.RED, Color.RED));
seek.setOrientation(JProgressBar.HORIZONTAL);
seek.setOpaque(false);
seek.setLocation(10, 50);
seek.setSize(300, 20);
seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
seek.setMinimum(0);
seek.setMaximum(1000);
seek.setBorder(new MatteBorder(5, 5, 5, 5, Color.CYAN));
}
protected void startThread()
{
Thread thread = new Thread(new Runnable(){
#Override
public void run()
{
try
{
while(true)
{
if(y == label.getHeight()){y = 1;}
label.repaint();
y += 1;
Thread.sleep(100);
}
}
catch(Exception ex){}
}
});
thread.start();
}
protected class Component extends JLabel
{
#Override
public void paintComponent(Graphics g)
{
Graphics2D gr = (Graphics2D) g;
gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gr.setColor(Color.RED);
gr.setFont(new Font("Calibri", Font.PLAIN, 16));
gr.drawString("Song Name", 50, y);
gr.dispose();
}
}
public static void main(String[] args)
{
new JSliderDemo();
}
}
The problem is, when I call repaint() for JLabel it automatically repaints JSlider with it even though JSlider is not included in JLabel.
Output :
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted.........
Now if I remove label.repaint() from the Thread, then the JSlider is not re-painted.
Output:
Slider re-painted
Slider re-painted
Is the repaint() method supposed to work like this?
In my last question, I was told to use Layout Manager and when I did use GridLayout just for checking if it's the solution, then it worked!
Only JLabel was repainted.
But I want to overlap JLabel on JSlider, so I thought of using JLayeredPane. And now, the problem is back.
How can I solve this?
Bottom Line : How can I overlap JLabel on JSlider without leading to repaint() method misbehave ?
OR
Does the repaint() method work like this?
As was already mentioned in the comments, the reason for your JSlider being repainted is that it has overlapping bounds with the JLabel. Even though your label doesn't paint over the area of the slider swing will still mark the overlapping area as dirty (i.e. the overlapping part of the slider will need to be repainted) because swing doesn't know that you are only painting in one part of the component.
To reduce the amount of repaints you will need to make the size of your JLabel smaller. Preferably only as large as it needs to be by invoking its getPreferredSize() method. You'll then be able to move the text by moving the location of the label.
Also you shouldn't be doing updates to the gui in a plain Thread. Use javax.swing.Timer instead. It ensures that all updates to the gui happen on the swing event thread, which is where they should be made.
After making these adjustments to your code the slider is only repainted while the label is actually visually over the slider.
public class JSliderDemo extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(JSliderDemo::new);
}
private final JLabel label = new CustomLabel();
public JSliderDemo() {
setSize(400, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
createWindow();
setVisible(true);
startTimer();
}
public void createWindow() {
JPanel panel = new JPanel(new BorderLayout());
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
label.setLocation(0, 0);
label.setBorder(new LineBorder(Color.RED));
label.setSize(label.getPreferredSize());
layeredPane.add(createSlider(), Integer.valueOf(50));
layeredPane.add(label, Integer.valueOf(100));
panel.add(layeredPane);
setContentPane(panel);
}
protected JSlider createSlider() {
JSlider seek = new CustomSlider();
seek.setOrientation(JProgressBar.HORIZONTAL);
seek.setOpaque(false);
seek.setLocation(10, 50);
seek.setSize(300, 20);
seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
seek.setMinimum(0);
seek.setMaximum(1000);
seek.setBorder(new LineBorder(Color.BLUE));
return seek;
}
private void startTimer() {
new Timer(100, e -> {
int y = label.getY();
int maxY = label.getParent().getHeight();
if (y == maxY) {
y = -label.getHeight();
}
label.setLocation(label.getX(), y + 1);
label.repaint();
}).start();
}
private static class CustomLabel extends JLabel {
protected CustomLabel() {
setFont(new Font("Calibri", Font.PLAIN, 16));
setText("Song Name");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Painting Label");
}
}
protected static class CustomSlider extends JSlider {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Painting Slider");
}
}
}
My question is how to display buttons on top of a circle which created with Graphics. My code is :
public class Grafik extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafik frame = new Grafik();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Grafik() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 784, 419);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnNewButton = new JButton("Click");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fire();
}
});
btnNewButton.setBounds(64, 73, 32, 32);
contentPane.add(btnNewButton);
}
public void fire()
{
JPanel panel = new JPanel(){
#Override
public void paint(Graphics g)
{
g.setColor(Color.black);
g.drawOval(20, 20, 400, 400);
g.fillOval(20,20,400,400);
g.setColor(Color.white);
g.drawOval(60, 60, 300, 300);
g.fillOval(60,60,300,300);
}
};
panel.setBounds(10, 27, 383, 233);
setContentPane(panel);
JButton btn = new JButton();
btn.setIcon(new ImageIcon("C:\\Users\\nuria\\Desktop\\icon1.png"));
btn.setBounds(75, 76, 32, 32);
panel.add(btn);
}
}
This code is a little part of my project. I have a lot of panels in my project and my fire method isn't called firstly. I mean the fire method is called by sixth panel. I have to draw two circles with buttons. These buttons should be between two circles. But i cant display buttons directly. When i hover the buttons, they show. I want to show buttons instantly when the sixth panel opens.
I have two buttons above. When the first button is clicked, another panel should open and show circles(which created with Graphics) and another button(with a icon) between them.
JPanel panel = new JPanel(){
#Override
public void paint(Graphics g)
{
Don't override paint(). Custom painting is done by overriding paintComponent() and don't forget to invoke super.paintComponent() as the first statement.
The problem with your current code is that by overriding paint you have changed the default painting logic of the panel and the child components are never painted.
Take a look at the section from the Swing tutorial on Custom Painting for more information and examples, especially the section on A Closer Look at the Paint Mechanism.
i read some contributions about this but nothing helped.
I try to make a little application with a gui,
but the problem is, if i click the button, no animation appears and nothing happens. I hope you can help me.
That's the code:
public class StartFrame extends JFrame{
JTextField eingabe;
JLabel inhalt;
JButton button;
JCheckBox fett;
JCheckBox kursiv;
JCheckBox groß;
JPanel panel;
StartFrame(int sizeWidth, int sizeHeight, String title){
setSize(sizeWidth, sizeHeight);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(title);
setLocationRelativeTo(null);
setLayout(null);
inhalt = new JLabel("TeXt");
inhalt.setBounds(0, 0, 500, 60);
Font font = inhalt.getFont().deriveFont(Font.ITALIC, 15);
inhalt.setFont(font);
inhalt.setToolTipText("Das ist ein Text");
add(inhalt);
button = new JButton("HIER");
button.setBounds(100, 10, 100, 50);
button.addActionListener(new ClickListener());
button.setEnabled(false);
add(button);
eingabe = new JTextField();
eingabe.setBounds(300, 50, 150, 25);
eingabe.addCaretListener(new SchreibkopfListener());
add(eingabe);
panel = new JPanel();
panel.setLayout(null);
panel.setBounds(10, 200, 150, 100);
add(panel);
fett = new JCheckBox("Fett");
fett.setBounds(0, 0, 150, 25);
fett.addItemListener(new FettListener());
panel.add(fett);
kursiv = new JCheckBox("Kursiv");
kursiv.setBounds(0, 25, 150, 25);
panel.add(kursiv);
groß = new JCheckBox("Groß");
groß.setBounds(0, 50, 150, 25);
panel.add(groß);
setVisible(true);
}
private class ClickListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
inhalt.setText(eingabe.getText());
}
}
private class SchreibkopfListener implements CaretListener{
#Override
public void caretUpdate(CaretEvent arg0) {
String inTextField = eingabe.getText();
inTextField = inTextField.trim();
if(inTextField.isEmpty()){
button.setEnabled(false);
}else{
button.setEnabled(true);
}
}
}
private class FettListener implements ItemListener{
#Override
public void itemStateChanged(ItemEvent arg0) {
if(fett.isSelected()){
Font font = inhalt.getFont().deriveFont(Font.BOLD, 15);
inhalt.setFont(font);
}else{
Font font = inhalt.getFont().deriveFont(Font.ITALIC, 15);
inhalt.setFont(font);
}
}
}
}
Here's a wonderful lesson into why null layouts suck (and you should stop using them)
Let's just take a little look at these lines...
nhalt = new JLabel("TeXt");
inhalt.setBounds(0, 0, 500, 60);
inhalt.setToolTipText("Das ist ein Text");
//...
button = new JButton("HIER");
button.setBounds(100, 10, 100, 50);
So, the label starts at 0x0 and expands through 500x60, okay, the button starts at 100x10 and expands through 100x50, this means that the label and the button actually collide
Now, I know what you're thinking, but I add the button after the label, but this isn't how components actually get painted/respond to events.
Components are painted in reverse order of how they are added, this means that the label actually resides OVER the button (in terms of the Z-order), this also means that the label receives events BEFORE the button, this is important because...
inhalt.setToolTipText("Das ist ein Text");
installs a MouseListener on the JLabel, which consumes ALL mouse events, preventing the button from been notified.
So, long answer short, don't use null layouts (and take the time to better understand how the API actually works :P)
so I remember about 2 years ago I had an issue with displaying an icon on a label on a mac.
I've tried to do it again this year whilst working on a project and still have the same issue. Could anyone check my code works on a different computer? Either mac or windows just so I know the code works and also if anyone has any idea why it doesn't work on mine let me know!
All that happens is the frame appears with the text and buttons but no background image.
public class MemoryRoom extends JPanel {
/** Background image of the menu screen */
private Image bg = new ImageIcon("memoryRoom.jpg").getImage();
/** JFrame used in the entire game */
protected JFrame app;
public MemoryRoom(JFrame app) {
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
app.setSize(1150, 680);
this.app = app;
initialize();
app.repaint();
}
protected void initialize() {
//final JPanel menuScreenPanel = new JPanel();
setVisible(true);
setSize(1150, 680);
setLayout(null);
JLabel lblSelectGame = new JLabel("Please select the game you wish to play:");
lblSelectGame.setBounds(320, 180, 600, 50);
add(lblSelectGame);
lblSelectGame.setFont(new Font("Dialog", Font.BOLD, 24));
lblSelectGame.setForeground(Color.WHITE);
JButton btnSnakesAndLadders = new JButton("Snakes and Ladders");
btnSnakesAndLadders.setBounds(370, 250, 200, 45);
add(btnSnakesAndLadders);
JButton btnDansCrazyTic = new JButton("Dan's Crazy Tic Tac Toe");
btnDansCrazyTic.setBounds(590, 250, 200, 45);
add(btnDansCrazyTic);
btnDansCrazyTic.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent TicTacToeEvent) {
setVisible(false);
}
});
btnSnakesAndLadders.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent SnakesAndLaddersEvent) {
setVisible(false);
}
});
app.getContentPane().add(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bg, 0, 0, 1150, 680, this);
}
public static void main (String args []){
new MemoryRoom(new JFrame());
}
}
I am trying to make a program to java and i have the common problem with flickering. I have try many things to eliminate but all the same. while the oval that i paint is moving the japplet is flickering. i need your help to solve this problem. here is my code:
import java.awt.Color;
public class all extends JApplet implements Runnable {
double x=0;
double y=0;
int m=0;
int n=0;
int f=30;
int μ=0;
Thread kinisi;
JPanel panel;
JFrame frame;
private boolean running = false;
private JTextField textField1;
private JTextField textField2;
Image backGround;
JPanel panel_3;
Image bf = createImage(m, n);
private Graphics doubleg;
private Image i;
public void init() {
this.setSize(800, 700);
}
public all() {
getContentPane().setLayout(null);
JButton btnNewButton = new JButton("Start");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String b=textField2.getText();
String z =textField1.getText();
if (textField1.getText().equals("") ||
textField2.getText().equals("")){
JOptionPane.showMessageDialog(
new JFrame(),
"Δωστε τιμή για το φ και το μ!",
"ERROR",JOptionPane.ERROR_MESSAGE);
} else{
f = Integer.parseInt(b);
μ = Integer.parseInt(z);
Start(); }
}
});
btnNewButton.setBounds(469, 168, 89, 23);
getContentPane().add(btnNewButton);
JButton btnStop = new JButton("Pause");
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pause();
}
});
btnStop.setBounds(588, 168, 89, 23);
getContentPane().add(btnStop);
JButton btnReset = new JButton("Reset");
btnReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Reset();
}
});
btnReset.setBounds(701, 168, 89, 23);
getContentPane().add(btnReset);
JLabel label = new JLabel("\u03BC");
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setBounds(549, 63, 46, 14);
getContentPane().add(label);
textField1 = new JTextField();
textField1.setBounds(529, 101, 86, 20);
getContentPane().add(textField1);
textField1.setColumns(10);
JLabel label_1 = new JLabel("\u03C6");
label_1.setHorizontalAlignment(SwingConstants.CENTER);
label_1.setBounds(681, 63, 46, 14);
getContentPane().add(label_1);
textField2 = new JTextField();
textField2.setBounds(667, 101, 86, 20);
getContentPane().add(textField2);
textField2.setColumns(10);
JButton btnNewButton_1 = new JButton("");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(
new JFrame(),
"Οδηγίες προγράμματος","Οδηγίες",
JOptionPane.INFORMATION_MESSAGE);
}
});
btnNewButton_1.setIcon(
new ImageIcon(all.class.getResource("/Images/info.png")));
btnNewButton_1.setBounds(732, 5, 39, 35);
getContentPane().add(btnNewButton_1);
JLabel label_2 = new JLabel("");
label_2.setIcon(
new ImageIcon(all.class.getResource("/Images/earth.jpg")));
label_2.setBounds(-20, 0, 820, 361);
getContentPane().add(label_2);
JPanel panel_1 = new JPanel();
panel_1.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_1.setBounds(10, 372, 369, 290);
getContentPane().add(panel_1);
JPanel panel_2 = new JPanel();
panel_2.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_2.setBounds(408, 372, 369, 290);
getContentPane().add(panel_2);
}
public void paint(Graphics g){
super.paint(g);
g.drawLine(0,f,350,200);
g.drawLine(0,200,350,200);
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
//Graphics2D g2d = (Graphics2D) g;
g.drawLine(460,400,460,650);
g.drawLine(20, 620, 350, 620);
g.drawLine(50,400,50,650);
g.drawLine(430, 620, 760, 620);
}
public void Start() {
kinisi = new Thread(this);
kinisi.start();
running = true;
}
public void run() {
while (running) {
if (x < 340){
double l = 200-f;
double k = l/350;
double y=k*x+f-30;
x= x+1;
m = (int) x;
n = (int) y;
repaint();
try {
Thread.sleep(μ);
} catch (InterruptedException ie) {}
}
}
}
public void update(Graphics g) {
if(i==null){
i=createImage(800,700);
doubleg = i.getGraphics();
}
doubleg.setColor(getBackground());
doubleg.fillRect(0,0,800,700);
doubleg.setColor(getForeground());
paint(doubleg);
g.drawImage(i,0,0,this);
}
public void paint1(Graphics g){
g.drawLine(0, f ,350, 200);
g.drawOval(m, n, 40, 40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
}
public void pause() {
if (kinisi != null) {
running = false;
}
}
public boolean Reset() {
if (kinisi != null) {
running = false;
kinisi.interrupt();
kinisi = null;
x=0;
y=0;
f=30;
m=0;
n=0;
repaint();
textField1.setText("");
textField2.setText("");
}
Graphics g = getGraphics();
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
return false;
}
public static void main(String[] args) {
JFrame frame = new JFrame("FISIKI");
frame.getContentPane().add(new all());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
frame.setResizable(false);
}
}
Thank you very much and sorry for my english are not very good!
There are a number of things that jump out at me.
You're extending from JApplet, but are adding it to a JFrame
You're mixing components with you custom painting
Not using layout managers.
Using getGraphics.
Firstly...
You should never override paint of a top level container (like JApplet). There are many reasons and you've found one. Top level containers are not double buffered. Instead, you should be creating a custom component (by extending something like JPanel) and overriding it's paintComponent method...
Secondly
Decided how you application is going to be. Is it an applet or application? If you follow the first point, then it really doesn't matter, as you only simply need to add the panel to the top level container.
Thirdly
I would create a panel that did the custom painting. Then I would create separate containers for all the fields and other parts of the application. This will allow you to separate the areas of responsibility. It would also allow you to use layout managers ;)
Fourthly
Use layout managers. The layout manager API has being designed to solve one of this most annoying aspects of GUI design, you're asking for a lot of trouble and work you decided to discard it - IMHO.
Fifthly
getGraphics should never be used. Apart from the fact that it can return null, it is only a snap shot of what is currently on the screen. As soon as the RepaintManager decides to perform a repaint, anything rendered to it will be lost. You should use paintComponent to update the state of your custom pane.