Good afternoon,
As a personal project intended to help me practice using JPanels and subclasses, I am coding a professional web portfolio containing my education, work and volunteer experience, and other notable works using JApplets.
I have the layout set to BorderLayout with the JButtons aligned WEST. When a button is clicked, the JPanels in the CENTER are supposed to switch out with the appropriate panel. However, I am not that far yet.
As of now, I only have a JLabel onto my Home JPanel that says "Home," because I'd like to make sure the method from the Home JPanel class is working before doing anything more. The issue is that the JPanel isn't displaying on the applet.
The thing is, when I move all the code into from the JPanel's class onto the main class, it displays just fine. So I know the problem is with either how I'm constructing the method, or with how I constructed my JPanel's class.
I've tried setting it to visible-- that didn't work. I've tried setting the LayoutManager as a parameter for the class constructor, I've tried adding paintComponent and super.paint(g), I tried using this.home.addHomePanel-- but nothing worked.
I know I'm missing a few things. It would be appreciated if someone could give me a hand. Please let me know if you need more information. Thank you for reading.
Main Class:
public class myWebFolio extends JApplet implements ActionListener
{
JButton[ ] menu =
{
new JButton("Home"),
new JButton("Education"),
new JButton("Work Experience"),
new JButton("Programming Projects"),
new JButton("Other")
};
//adds panel to memory
private JPanel buttonPanel = new JPanel();
private Home home;
public void init()
{
setLayout (new BorderLayout( ) ); //changes the layout of the appl
home = new Home();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
/*
* Adds an ActionListener to each button
* and then adds the button to the buttonPanel.
* Also adds an invisible componenet to give the buttons
* spacing.
*/
for (int i=0; i<menu.length; i++)
{
menu[i].addActionListener(this);
buttonPanel.add(Box.createVerticalStrut(100));
buttonPanel.add(menu[i]);
}
add(buttonPanel,BorderLayout.WEST);
home.addHomePanel();
}
public void actionPerformed(ActionEvent event)
{
}
public void paintComponent(Graphics g)
{
super.paint(g);
}
}
Home Panel's Class:
public class Home extends JPanel
{
JPanel homePanel = new JPanel(new FlowLayout());
JLabel label = new JLabel("Home");
/**
* Constructor for objects of class Home
*/
public Home()
{
}
public void addHomePanel()
{
homePanel.add(label, FlowLayout.LEFT);
homePanel.setVisible(true);
add(homePanel, BorderLayout.CENTER);
}
public void paintComponent(Graphics g)
{
super.paint(g);
}
}
Related
I have created a simple game in Swing which has a screen. Clicking on a cell results in color change of two adjacent cells. This is achieved by this code:
public class SelfGrid extends BattleGrid {
#Override
protected JPanel getCell()
{
JPanel panel = new JPanel();
panel.setBackground(Color.black);
panel.setBorder(BorderFactory.createLineBorder(Color.blue, 1));
panel.setPreferredSize(new Dimension(20, 20));
panel.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e)
{
panel.setSize(new Dimension(20,80));
panel.setBackground(Color.orange);
}
}
});
return panel;
}
}
public abstract class Battle extends JPanel {
public BattleGrid() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel grid = new JPanel();
grid.setLayout(new GridLayout(0,10));
JPanel panel = new JPanel();
panel = getCell();
grid.add(panel);
}
}
this.add(grid);
}
protected abstract JPanel getCell();
}
When I use setVisible(boolean) method to toggle between two screens and the original screen is brought back, only the cells that were clicked on remain colored. In other words, the dimension of each JPanel is restored to 20,20. I was told that this is because setVisible() method actually repaints components on the screen. How can I bring back the original screen without any changes being made to it contents? Thank you.
Instead of making programatic color changes directly to the UI elements, create a two dimensional array that represents the colors of the cells, and modify that. Then, repaint the cells based off the values in the array each time visibility changes or a cell is clicked.
I'm trying to understand what actually paints components in Swing. I read this article about painting in AWT and Swing and now tried to write the following simple program:
//A simple wrapper to understan how paint() works
public class MyButton extends JButton{
/**
* Default serialVersionUID
*/
private static final long serialVersionUID = 1L;
private final JButton jButton;
public MyButton(JButton jButton) {
this.jButton = jButton;
}
#Override
public void paint(Graphics g){
jButton.paint(g);
}
}
But when I try to add MyButton to frame
JFrame frame = new JFrame("Hello swing");
JPanel panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(new MyButton(button));
frame.add(panel);
it renders nothing
But after deleting
#Override
public void paint(Graphics g){
jButton.paint(g);
}
it renders the empty button:
QUESTION: Why does it behave that way? Why does the delegating cause rendering to fail?
First of all when you post a question you should post a proper SSCCE that demonstrates the problem. We can't copy/compile random lines of code. Until a problem is solved, you don't know what part of the code is causing the problem.
Why does the delegating cause rendering to fail?
My guess would be that the size of the button is (0, 0) so there is nothing to paint.
When you get rid of the custom paint method, then the real button can be painted because it does have a size because the layout manager has done its job.
public class Demo extends JFrame{
public static void main(String[] args)
{
JPanel panel = new JPanel();
getContentPane().setLayout(new BorderLayout());
panel.add(new JButton("Test"));
this.getContentPane().add(panel, BorderLayout.CENTER);
this.setSize(200,200);
this.setVisible(true);
}
}
If you want to add UI Components do it like that, don't use paint in any way.
If you want to paint for example a rectangle follow this tutorial: https://docs.oracle.com/javase/tutorial/uiswing/painting/
Your paint method does not draw the MyButton object, but instead draws the JButton which is member of your class. The problem now is, that this Button has not been added to the panel and so it's drawn on nothing. By removing your paint method, super.paint(g) is called because your class has no paint method and so your button, but not the member JButton is drawn.
I hope you understand what I am trying to explain to you.
I Have applet with a image of a java cup that can be repositioned by the clicking of 5 buttons to move it in the main area of the applet window.
the issue im having is the buttons are not being displayed in im applet the only thing that is showing is my cup.gif on the blue background, can any one see the problem with the code ,i want the buttons to show and work
And yes guys I know AWT is old but i have to learn it for my course...any help would be great thanks guys!
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class moveIt extends Applet implements ActionListener
{
private Image cup;
private Panel Keypad = new Panel();
public int top = 15;
public int left = 15;
private Button Keyarray[] = new Button[5];
public void init ()
{
cup=getImage(getDocumentBase(), "cup.gif");
Canvas myCanvas= new Canvas();
Keyarray[0] = new Button ("Up");
Keyarray[1] = new Button ("Left");
Keyarray[2] = new Button ("Down");
Keyarray[3] = new Button ("Right");
Keyarray[4] = new Button ("Center");
setBackground(Color.BLUE);
Panel frame = new Panel();
frame.setLayout(new BorderLayout());
frame.add(myCanvas, BorderLayout.NORTH);
frame.add(Keypad, BorderLayout.SOUTH);
Keypad.setLayout(new BorderLayout());
Keypad.add(Keyarray[0], BorderLayout.NORTH);
Keypad.add(Keyarray[1], BorderLayout.WEST);
Keypad.add(Keyarray[2], BorderLayout.SOUTH);
Keypad.add(Keyarray[3], BorderLayout.EAST);
Keypad.add(Keyarray[4], BorderLayout.CENTER);
Keyarray[0].addActionListener(this);
Keyarray[1].addActionListener(this);
Keyarray[2].addActionListener(this);
Keyarray[3].addActionListener(this);
Keyarray[4].addActionListener(this);
}//end of method init
public void paint(Graphics g)
{
g.drawImage(cup, left, top, this);
}
public void actionPerformed(ActionEvent e)
{
String arg= e.getActionCommand();
if (arg.equals("Up"))
top -= 15;
if (arg.equals("down"))
top += 15;
if (arg.equals("Left"))
left -= 15;
if (arg.equals("Right"))
left += 15;
if (arg.equals("Center"))
{
top=60;
} left=125;
repaint();
}//end paint method
}//end of class
You never add the frame to the applet this.add(frame)
Once you do, you will have to setOpaque(false) to the frame so you can see the background
Important Side Notes:
Instead of painting on the Applet directly, you should be painting rather on a JPanel and override it's paintComponent method.
You Need to call super.paint(g) or super.paintComponent(g)(for JPanel) in the paint method, as to not break the paint chain and see all kinds of wierd paint artifacts
I just noticed the AWT components. AWT is pretty much obsolete. You should move it up to using Swing. See the Swing Tutorials
Use Java naming convention. Variables begin with lower case letters, using camelCasing e.g. Keyarray → keyArray. Class names begin with capital letters using CamelCasing e.g. moveIt → MoveIt
This is not a repeat question. Yes there are similar, but none have provided a working answer.
public class Tool extends JPanel implements ActionListener{
public JPanel Panel;
public Tool() {
}
public void show(){
displayStuff();
Panel.setVisible(true);
revalidate();
repaint();
}
}
Tool MyTool = new Tool();
JPanel Master = new JPanel();
JPanel Dash = = new JPanel();
JTabbedPane Tabs = new JTabbedPane();
JTabbedPane Tabs.addTab("Dash", Dash);
JTabbedPane Tabs.addTab("Tool", MyTool.Panel);
Master.add(Tabs);
The real code is much more complex. But the basic issue is that when changes occurs on MyTool.Panel as a result of user pressing some buttons.
MyTool.Panel does NOT get repainted until I use mouse to move Master.
How can I force it to repaint?
Its not a perfect solution but you can validate and redraw the entire application, thats what I have done in the past. I've used something like
class MyPanel extends JPanel{
public void doRedraw(){
getTopLevelAncestor().revalidate();
getTopLevelAncestor().repaint();
}
}
Hope this helps.
The code has a JPanel with an inner JPanel that displays awt drawing. Upon mouseclick the inner JPanel is to be replaced by one of its polymorphic siblings. This code isn't replacing the jPanel.
class ContentPanel extends JPanel {
private GraphicPanel graphicPanel;
public ContentPanel(GraphicPanel graphicPanel) {
this.graphicPanel = graphicPanel;
add(this.graphicPanel);
public void setGraphicPanel(GraphicPanel graphicPanel) {
this.graphicPanel = graphicPanel;
// invalidate();
// revalidate();
// repaint();
}
Setting the graphicPanel to a polymorphic relative doesn't cause any errors, it just isn't painting the new graphicPanel. Using cardLayout is not preferred, there must be a cleaner way. How to proceed?
in setGraphicPanel, you need to remove the current graphicPanel and add the new one. THEN call revalidate.
something like this:
public void setGraphicPanel(GraphicPanel graphicPanel) {
this.removeAll();
this.graphicPanel = graphicPanel;
this.add(graphicPanel);
this.revalidate();
}
Although CardLayout was designed to do just this thing. Are you sure you don't want to use CardLayout?