I already looked up this problem and found several threads. Tried all the solutions and none of them helped. I am trying to show a cross where my mouse is placed, the x and the y coordinate of my current mouse position is supposed to be shown in the top left and top right corner. In order to achieve this, I used two JLabels.
Maybe I am overlooking something?
I played around with the standard Text I set in the Labels, positioning, different Layouts for my frame and panel - nothing helps.
The following code should be good enough to get an understanding, I dont think it would be helpful if I left out something.
Fensterkreuz(){
jl1 = new JLabel("0");
jl2 = new JLabel("0");
jl1.setSize(new Dimension(100,100));
jl2.setSize(new Dimension(100,100));
jl1.setFont(new Font ("Arial", Font.PLAIN, 15));
jl2.setFont(new Font ("Arial", Font.PLAIN, 15));
cP = new Point();
this.add(jl1);
this.add(jl2);
addMouseMotionListener(this);
}
public void mouseDragged (MouseEvent e){
}
public void mouseMoved (MouseEvent e) {
cP = e.getPoint();
repaint();
}
public void paint (Graphics g){
g.drawLine((cP.x),(cP.y-15), (cP.x),(cP.y+15));
g.drawLine((cP.x-15),(cP.y), (cP.x+15),(cP.y));
jl1.setText(String.valueOf(cP.x));
jl2.setText(String.valueOf(cP.y));
}
public static void main (String [] args) {
JFrame f = new JFrame();
JComponent test = new Fensterkreuz();
test.setOpaque(false);
f.setVisible(true);
f.setSize(1500,1000);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(test);
}
Put repaint() at the bottom of your main method. Repaint calls the Paint method you have but I think you also have to add your own overriding repaint method to stop “flickering”.
You are overriding the paint() method. So, you need add super.paint(g); as the first line in your overridden paint() method.
To show the 2 labels properly, you need to add this.setLayout(new FlowLayout(FlowLayout.LEFT)); line.
I'm adding the full code with above changes here, so that you can run it and see the results yourself.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Fensterkreuz extends JComponent implements MouseMotionListener {
private JLabel jl1;
private JLabel jl2;
private Point cP;
Fensterkreuz(){
jl1 = new JLabel("0");
jl2 = new JLabel("0");
jl1.setSize(new Dimension(100,100));
jl2.setSize(new Dimension(100,100));
jl1.setFont(new Font ("Arial", Font.PLAIN, 15));
jl2.setFont(new Font ("Arial", Font.PLAIN, 15));
cP = new Point();
//this.setLayout(new FlowLayout(FlowLayout.LEFT));
//this.add(jl1);
//this.add(jl2);
this.setLayout(new GridBagLayout());
this.add(jl1, new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
this.add(jl2, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHEAST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
addMouseMotionListener(this);
}
public void mouseDragged (MouseEvent e){
}
public void mouseMoved (MouseEvent e) {
cP = e.getPoint();
repaint();
}
public void paint (Graphics g){
super.paint(g);
g.drawLine((cP.x),(cP.y-15), (cP.x),(cP.y+15));
g.drawLine((cP.x-15),(cP.y), (cP.x+15),(cP.y));
jl1.setText(String.valueOf(cP.x));
jl2.setText(String.valueOf(cP.y));
}
public static void main (String [] args) {
JFrame f = new JFrame();
JComponent test = new Fensterkreuz();
test.setOpaque(false);
f.setVisible(true);
f.setSize(1500,1000);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(test);
}
}
Related
I want to change each buttons width but it's not working (i'am new in swing)
Panel = new JPanel();
gl = new GridLayout(2, 1);
Panel.setLayout(gl);
add(Panel, BorderLayout.EAST);
Up= new JButton("Btn1");
Up.addActionListener(this);
Up.setPreferredSize(new Dimension(200,150));
Panel.add(Up);
Down = new JButton("Btn2");
Down.addActionListener(this);
Down.setPreferredSize(new Dimension(200,300));
Panel.add(Down);
For this case I would use the GridBagLayout. This can be adapted very well with the GridBagConstraints.
In your case the weighty parameter would be responsible for controlling the height of the button in the panel. This is given as a percentage.
The code would look like this:
panel = new JPanel(new GridBagLayout());
add(panel, BorderLayout.EAST);
up = new JButton("Btn1");
up.addActionListener(this);
up.setPreferredSize(new Dimension(200, 150));
panel.add(up, new GridBagConstraints(0, 0, 1, 1, 100, 33, GridBagConstraints.NORTH, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0,0));
down = new JButton("Btn2");
down.addActionListener(this);
down.setPreferredSize(new Dimension(200, 300));
panel.add(down, new GridBagConstraints(0, 1, 1, 1, 100, 66, GridBagConstraints.NORTH, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0,0));
The result looks like this:
This question already has an accepted answer, but just wanted to put some 'tweaks' into an answer.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class BigWideButtons {
private JComponent ui = null;
static int upCodepoint = 9206; // upward triangle
static int downCodepoint = 9207; // downward triangle
Insets insets = new Insets(0, 75, 0, 75); // wide insets
Font font = getCompatibleFont().deriveFont(120f); // big font
BigWideButtons() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridLayout(0, 1, 10, 10));
ui.setBorder(new EmptyBorder(4,4,4,4));
addButton(upCodepoint);
addButton(downCodepoint);
}
private void addButton(int codepoint) {
JButton b = new JButton(new String(Character.toChars(codepoint)));
b.setFont(font);
b.setMargin(insets);
ui.add(b);
}
private static Font getCompatibleFont() {
Font[] fonts = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAllFonts();
for (Font font : fonts) {
if (font.canDisplay(upCodepoint) &&
font.canDisplay(downCodepoint)) {
System.out.println("Font: " + font.getFamily());
return font;
}
}
return null; // No installed font supports these characters!
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
BigWideButtons o = new BigWideButtons();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
This answer:
Uses a GridLayout, as seen in the question.
Avoids the need to guess a required size - it simply makes the font and button margin large, then packs the frame to fit them.
Given the meaning of the buttons 'up & down' it uses triangles pointing in those directions, as available in the Unicode character set.
But fonts do not typically have glyphs for every Unicode character (the character set is huge), so it adds a method which finds a font (the first available) which supports those glyphs. Here it uses "Segoe UI Symbol".
I am just throwing together a quick and dirty GUI to display some data when I ran into an odd issue. The last label I add to the JFrame doesn't want to be positioned or display the border I put on it, so it looks like this:
Here is my code:
public DisplayData (Connection tConn)
{
ID = tID;
conn = tConn;
setupObjects();
setupFrame();
}
private void setupObjects()
{
JLabel caseLabel = new JLabel ("Case #:");
JLabel dateLabel = new JLabel ("Date:");
JLabel reportLabel = new JLabel ("Report:");
JLabel offenceLabel = new JLabel ("Offence:");
JLabel descriptionLabel = new JLabel ("Description:");
this.add(caseLabel);
this.add(dateLabel);
this.add(reportLabel);
this.add(offenceLabel);
this.add(descriptionLabel);
caseLabel.setBounds(50, 50, 130, 25); //x, y, width, height
dateLabel.setBounds(50, 100, 130, 25);
reportLabel.setBounds(50, 150, 130, 25);
offenceLabel.setBounds(50, 200, 130, 25);
descriptionLabel.setBounds(100, 50, 130, 25);
caseLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
dateLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
reportLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
offenceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
descriptionLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
private void setupFrame()
{
this.setTitle("Data Display");
this.setSize (650, 700); //Width, Height
this.setLocation(300, 10);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
}
Yes, I know I should be using a proper layout manager, but like I said i just wanted something quick and dirty. Plus, I will not be beaten by something that should be this simple. Any ideas would be appreciated.
EDIT:
As Compass and Neophyte pointed out, my order of operations was off. Flipped my method calls and all is good again in the world. Thanks for the 2nd pair of eyes.
Contrary to the original poster's strategy, or any of the answers so far, the best approach to this problem is to use layouts.
Here is an example that shows how easy it is to position fields using layouts, and to change the GUI on later updates to the specification.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class CourtDetailsGUI {
private JComponent ui = null;
static final String[] FIELD_NAMES = {
"Case #:",
"Date:",
"Report:",
"Offence:",
"Plaintiff:",
"Defendant:"
};
CourtDetailsGUI(int num) {
initUI(num);
}
public void initUI(int num) {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getFieldsPanel(num), BorderLayout.PAGE_START);
JTextArea ta = new JTextArea(5, 40);
JScrollPane sp = new JScrollPane(ta);
JPanel p = new JPanel(new GridLayout());
p.add(sp);
p.setBorder(new TitledBorder("Details"));
ui.add(p);
}
private JPanel getFieldsPanel(int num) {
JPanel outerPanel = new JPanel(new FlowLayout());
JPanel innerPanel = new JPanel(new GridLayout(0, 1, 15, 15));
outerPanel.add(innerPanel);
for (int ii=1; ii<num; ii++) {
JLabel l = new JLabel(FIELD_NAMES[ii]);
l.setBorder(new LineBorder(Color.BLACK));
innerPanel.add(l);
}
return outerPanel;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
for (int ii=0; ii<FIELD_NAMES.length; ii++) {
CourtDetailsGUI o = new CourtDetailsGUI(ii+1);
JFrame f = new JFrame("Data " + (ii+1));
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
}
};
SwingUtilities.invokeLater(r);
}
}
Your order of operations is incorrect.
You initially call setupObjects();
This plays your objects out onto a JFrame, which has the default LayoutManager of BorderLayout.
By using the default add(Component comp) method, with BorderLayout, you end up putting the component into null for BorderLayout, which is not supposed to be normal. Furthermore, the reason you can't see the border for this object is because the border is actually the size of the frame. If you explicitly set a region for BorderLayout, then you'll see it work, but setting to no region seems to just break BorderLayout.
Additional add calls appear to free the previous item from the BorderLayout null management, allowing the bounds to take over.
Afterwards, you call setupFrame(); which removes the layout manager, but does not refresh what is currently rendered.
This sets the layout to null, which does nothing to how the frame is displayed, but just removes the layout.
To avoid this issue, call setupFrame(); prior to setupObjects();, and then setVisible(true) can be called at the end of setupObjects();
Im trying to draw a simple rectangle on a frame with some scrollbars and textfields(just testing) but the paintComponent its not showing, ive seen some similar cases here but i cant manage to make it work, any help please?
package appletdeslizadores;
import java.awt.*;
import javax.swing.*;
public class frame extends JPanel {
JFrame f1;
JPanel p1, p2;
JLabel lbl1, lbl2, lbl3;
JTextField txtfld1, txtfld2, txtfld3;
JScrollBar sbar1, sbar2, sbar3;
public frame() {
f1 = new JFrame("Applet ScrollBars");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setSize(380, 350);
f1.setLayout(new FlowLayout());
p1 = new JPanel(new GridLayout(3,3,10,10));
lbl1 = new JLabel("Scroll Bar 1");
lbl2 = new JLabel("Scroll Bar 2");
lbl3 = new JLabel("Scroll Bar 3");
sbar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar2 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar3 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
txtfld1 = new JTextField(3);
txtfld1.setText(String.valueOf(sbar1.getValue()));
txtfld1.setEditable(false);
txtfld2 = new JTextField(3);
txtfld2.setText(String.valueOf(sbar2.getValue()));
txtfld2.setEditable(false);
txtfld3 = new JTextField(3);
txtfld3.setText(String.valueOf(sbar3.getValue()));
txtfld3.setEditable(false);
p1.add(lbl1);
p1.add(lbl2);
p1.add(lbl3);
p1.add(sbar1);
p1.add(sbar2);
p1.add(sbar3);
p1.add(txtfld1);
p1.add(txtfld2);
p1.add(txtfld3);
f1.add(p1);
f1.setVisible(true);
}
public void paintComponent(Graphics2D g) {
g.drawRect(50,50,70,100);
g.setColor(Color.red);
}
public static void main(String[] args) {
new frame();
}
}
Problem
You're not sticking to conventions. This is causing problems small mistakes. Your frame class is actually a JPanel, not a JFrame.
There are two main problems: You never added the panel to the frame, and the paintComponent() method has a Graphics object, not a Graphics2D object as a parameter.
The changes to your code are at the bottom of this answer.
Solution
Stick to conventions. (You should also rename your class to a more appropriate name, but that is your choice.) Add the #Override annotation to your paintComponent() method since you wish to override this method from the original JPanel. If it crashes because of the annotation, it means you are not overriding correctly.
Change the paintComponent() parameter from Graphics2D to Graphics.
Add the JPanel to the JFrame.
Make sure you call setPreferredSize() on your JPanel and specify a size.
Call pack() on the JFrame right before making it visible so the layout manager can place everything accordingly.
Now I'm sure by the end of all this you are still not going to be happy with what you see because the code still needs some work, but at least this should give you a boost into the right direction. Also, you may want to call setColor() before drawing the rectangle. ;)
Hope this helped.
Code
public class frame extends JPanel {
JFrame f1;
JPanel p1, p2;
JLabel lbl1, lbl2, lbl3;
JTextField txtfld1, txtfld2, txtfld3;
JScrollBar sbar1, sbar2, sbar3;
public frame() {
f1 = new JFrame("Applet ScrollBars");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setSize(380, 350);
f1.setLayout(new FlowLayout());
p1 = new JPanel(new GridLayout(3,3,10,10));
lbl1 = new JLabel("Scroll Bar 1");
lbl2 = new JLabel("Scroll Bar 2");
lbl3 = new JLabel("Scroll Bar 3");
sbar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar2 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
sbar3 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10, 0, 255);
txtfld1 = new JTextField(3);
txtfld1.setText(String.valueOf(sbar1.getValue()));
txtfld1.setEditable(false);
txtfld2 = new JTextField(3);
txtfld2.setText(String.valueOf(sbar2.getValue()));
txtfld2.setEditable(false);
txtfld3 = new JTextField(3);
txtfld3.setText(String.valueOf(sbar3.getValue()));
txtfld3.setEditable(false);
p1.add(lbl1);
p1.add(lbl2);
p1.add(lbl3);
p1.add(sbar1);
p1.add(sbar2);
p1.add(sbar3);
p1.add(txtfld1);
p1.add(txtfld2);
p1.add(txtfld3);
f1.add(p1);
setPreferredSize(new Dimension(512, 512));
f1.add(this);
f1.pack();
f1.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
g.drawRect(50,50,70,100);
g.setColor(Color.red);
}
public static void main(String[] args) {
new frame();
}
}
For my end of the year project, I'm trying to make a game which helps a person study different questions, which are shown in a GUI. Ideally, buttons will be available for the user to press and see if their answer was correct. I have made the basis of the GUI with the variables, the ArrayList <String[]> variable which will hold the questions with their answers, and tried to make buttons.
However, when I try to run the program, the buttons (I only have one in the code shown) are cut off and I am unable to place them where they properly belong. Please help!
Somebody please show me a solution that actually has been tested and works! I can't seem to get it based off what has been posted for me so far!
Here's what it looks like when I run it:
And here's all of the program's code:
import java.awt.*;
import javax.swing.*;
import java.awt.geom.Line2D;
import java.util.*;
import java.awt.event.*;
public class EuroGUI extends JPanel {
//Instantiate necessary variables.
ArrayList <String[]> questions = new ArrayList <String[]>(); //Stores (Question + Answers, Correct Answer)
int width = 1280; //GUI Size
int height = 720; // ^
int correct = 0; //Number of correct answers
int attempted = 0; //Number of questions attempted
int streak = 0; //Number of correct answers in a row
int points = 0; //Points accumulated
Font title = new Font("Serif", Font.PLAIN, 60);
Font statsTitle = new Font("Serif", Font.PLAIN, 45);
Font sig = new Font("Mistral", Font.PLAIN, 45);
//Drop down options stuff
JMenu ddMenu = new JMenu("Select an option");
String[] dropDown = new String[] {"A", "B", "C", "D", "E"};
String completion = "starting"; //Determines if the first time repainting
Scanner keyboard = new Scanner(System.in); //Make a keyboard object to test stuff
public static void main(String[]args){ //Main Runner
EuroGUI g = new EuroGUI();
g.setUpScreen();
g.repaint();
}
public void setUpScreen() { //Create the physical GUI, which paints all graphics
//Used http://www.mathcs.emory.edu/~cheung/Courses/377/Syllabus/8-JDBC/GUI/Progs/Layout1.java for buttons
//Create actual GUI window and graphics.
//Create actual GUI window and graphics.
JFrame f = new JFrame("AP European History Study Tool");
JPanel panelGrid = new JPanel();
panelGrid.setLayout(new GridLayout());
setLayout(null);
JPanel panelBorder = new JPanel();
panelBorder.setLayout(new BorderLayout());
JButton xA = new JButton("Choice A");
panelGrid.add(xA, "West");
panelBorder.setLocation(500,500);
f.getContentPane().add(panelBorder);
f.setResizable(false);
f.setVisible(true);
f.setSize(width, height);
f.setBackground(Color.lightGray);
f.add(this);
}
public void paintComponent(Graphics g) { //Draws information on the GUI (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
Graphics2D g2 = (Graphics2D) (g);
//Draw a background box which will cover anything that was not re-painted over.
g.setColor(Color.lightGray);
g.fillRect (0, 1280, 0, 720);
//Title "interface"
//Change color back for the lines;
g.setColor(Color.blue);
//Enable bolder lines.
g2.setStroke(new BasicStroke(6));
//Create a box of lines around the title.
g2.draw(new Line2D.Double(200, 0, 200, 120));
g2.draw(new Line2D.Double(200, 120, 1070, 120));
g2.draw(new Line2D.Double(1070, 0, 1070, 120));
g2.draw(new Line2D.Double(200, 0, 1070, 0));
//Fill in box with title with some colors :)
g.setColor(Color.green);
g.fillRect (200, 0, 870, 120);
//Write title
g2.setFont(title);
g.setColor(Color.cyan);
g.drawString("AP European History Study Tool", 240, 80);
g.setColor(Color.black);
g.drawString("AP European History Study Tool", 238, 78);
//Signiature on Title
g.setColor(Color.white);
g2.setFont(sig);
g.drawString("by My Name", 600, 120);
g.setColor(Color.blue);
g.drawString("by My Name", 598, 118);
//Statistics Bar Outline
g.setColor(Color.blue);
g2.draw(new Line2D.Double(1000, 170, 1000, 670));
g2.draw(new Line2D.Double(1000, 170, 1280, 170));
g2.draw(new Line2D.Double(1280, 170, 1280, 670));
g2.draw(new Line2D.Double(1000, 670, 1280, 670));
g2.setStroke(new BasicStroke(6));
g.setColor(Color.black);
g.fillRect (1000, 170, 1280, 500);
g.setColor(Color.green); //Underline
g2.setStroke(new BasicStroke(2));
g2.draw(new Line2D.Double(1055, 230, 1215, 230));
g2.setStroke(new BasicStroke(6));
//Overall Score
g2.setFont(statsTitle);
g2.setColor(Color.green);
g.drawString("Statistics", 1055, 220);
g2.setColor(Color.cyan);
g.drawString(correct + "/" + attempted + " Correct", 1035, 285);
//Streak
if (streak >= 3)
{
g2.setColor(Color.red);
g.drawString(streak + " Streak", 1060, 340);
}
else{
g2.setColor(Color.cyan);
g.drawString(streak + " Streak", 1060, 340);
}
if (completion.equals("starting")){
}
}
}
This is a symptom of breaking the paint chain.
Graphics is a shared resources, that is, the same Graphics context is used to paint all the components within a paint cycle.
One of the jobs of paintComponent is to prepare the Graphics context for painting by clearing it before anything is painted to it.
So instead of...
public void paintComponent(Graphics g) { //Draws information on the GUI (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
Graphics2D g2 = (Graphics2D) (g);
Try using
public void paintComponent(Graphics g) { //Draws information on the GUI (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) (g);
Pixel perfect layouts are an illusion in modern UIs. You don't control factors like font metrics, dpi or rendering pipelines which all effect the amount of space individual components might need. Instead you should make use of appropriate layout managers and consider using compound layouts to produce more complex solutions
Updated with example
There are a number of things wrong, the main problem is, panelGrid isn't been added to anything. The null layout manager is also not helping.
You're also focusing all your efforts into a single panel, which is going to make life messy.
Instead, try separating each section into its own component and focus on there individual needs, you'll find it much easier to manage in the long run.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new HeaderPane(), BorderLayout.NORTH);
frame.add(new StatisticsPane(), BorderLayout.EAST);
frame.add(new QuestionPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HeaderPane extends JPanel {
public HeaderPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.SOUTH;
// gbc.ipadx = 100;
NamePane namePane = new NamePane();
FontMetrics fm = namePane.getFontMetrics(namePane.getFont());
add(namePane, gbc);
gbc.insets = new Insets(0, 0, fm.getDescent(), 0);
gbc.gridx = 0;
gbc.gridwidth = 2;
gbc.ipadx = 10;
gbc.ipady = 10;
gbc.anchor = GridBagConstraints.CENTER;
add(new TitlePane(), gbc);
}
public class ShadowLabel extends JPanel {
private String text;
private Color shadowColor;
private int shadowOffset;
public ShadowLabel(String text, Color shadowColor) {
this.text = text;
this.shadowColor = shadowColor;
this.shadowOffset = 2;
}
public int getShadowOffset() {
return shadowOffset;
}
public void setShadowOffset(int shadowOffset) {
this.shadowOffset = shadowOffset;
}
#Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(getFont());
return new Dimension(fm.stringWidth(getText()), fm.getHeight());
}
public String getText() {
return text;
}
public Color getShadowColor() {
return shadowColor;
}
public void setText(String text) {
this.text = text;
repaint();
}
public void setShadowColor(Color shadowColor) {
this.shadowColor = shadowColor;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(getFont());
FontMetrics fm = g.getFontMetrics();
int x = (getWidth() - fm.stringWidth(getText())) / 2;
int y = (getHeight() - fm.getHeight()) / 2;
g.setColor(getShadowColor());
g.drawString(getText(), x + getShadowOffset(), y + getShadowOffset() + fm.getAscent());
g.setColor(getForeground());
g.drawString(getText(), x, y + fm.getAscent());
}
}
public class TitlePane extends ShadowLabel {
public TitlePane() {
super("AP European History Study Tool", Color.CYAN);
setBackground(Color.GREEN);
setBorder(new MatteBorder(0, 1, 1, 1, Color.BLUE));
setFont(new Font("Serif", Font.PLAIN, 60));
}
}
public class NamePane extends ShadowLabel {
public NamePane() {
super("by Me", Color.WHITE);
setForeground(Color.BLUE);
setFont(new Font("Mistral", Font.PLAIN, 45));
setOpaque(false);
}
}
}
public class StatisticsPane extends JPanel {
private JLabel score;
private JLabel streak;
public StatisticsPane() {
setLayout(new BorderLayout());
setBackground(Color.BLACK);
setBorder(new CompoundBorder(new LineBorder(Color.BLUE), new EmptyBorder(4, 4, 4, 4)));
JLabel statistics = new JLabel("Statistics");
statistics.setFont(new Font("Serif", Font.PLAIN, 45));
statistics.setForeground(Color.GREEN);
statistics.setBorder(new CompoundBorder(new MatteBorder(0, 0, 1, 0, Color.GREEN), new EmptyBorder(4, 4, 4, 4)));
add(statistics, BorderLayout.NORTH);
score = new JLabel("0/0 correct");
score.setForeground(Color.GREEN);
score.setFont(new Font("Serif", Font.PLAIN, 45));
streak = new JLabel("0 streak");
streak.setForeground(Color.GREEN);
streak.setFont(new Font("Serif", Font.PLAIN, 45));
JPanel pnl = new JPanel(new GridBagLayout());
pnl.setOpaque(false);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
pnl.add(score, gbc);
gbc.gridy++;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.NORTH;
pnl.add(streak, gbc);
add(pnl);
}
}
public class QuestionPane extends JPanel {
public QuestionPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.WEST;
JButton xA = new JButton("Choice A");
add(xA, gbc);
}
}
}
I would also separate the management of the data and the UI, so that the data is managed by some kind of model or models which can respond to changes in the UI and visa-versa. This means that your UI becomes a visual representation of your data model and allows the two to decouple and work independently from each other...
Take a look Model–view–controller for more details. Note: Swing uses a version of this, but it's more like Model-View and Controller
You should also take a look at Creating a GUI With JFC/Swing to see how you make better use of the ready made components available in Swing
You did not set up your Layout properly. Might not be exactly what you are looking for but if you change from a FlowLayout to a BorderLayout it seems to fix your issue. Also you don't use panel2 anywhere in you code so you can remove it.
public void setUpScreen() { //Create the physical GUI, which paints all graphics
//Used http://www.mathcs.emory.edu/~cheung/Courses/377/Syllabus/8-JDBC/GUI/Progs/Layout1.java for buttons
//Create actual GUI window and graphics.
JFrame f = new JFrame("AP European History Study Tool");
JPanel panelGrid = new JPanel();
panelGrid.setLayout(new GridLayout());
setLayout(null);
JPanel panelBorder = new JPanel();
panelBorder.setLayout(new BorderLayout());
JButton xA = new JButton("Choice A");
panelGrid.add(xA, "West");
panelBorder.setLocation(500,500);
f.getContentPane().add(panelBorder);
f.setResizable(false);
f.setVisible(true);
f.setSize(width, height);
f.setBackground(Color.lightGray);
f.add(this);
}
I got a JPanel where a triangle is painted.
When someone clicks on a button the triangle should be repainted with new parameters. The problem is the old triangle is still there and the new one is messed up with part of the textfield underneath.
public class Vermessung {
private static void eingabe(){
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(screen.height/2, screen.height/4*3);
JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.PAGE_AXIS));
//Eingabebereich
JPanel eingabebereich = new JPanel(new GridLayout(3, 1));
JPanel abc = new JPanel(new GridLayout(4, 2));
abc.add(new JLabel("Strecke"));
abc.add(new JLabel("Gemessener Wert in [m]"));
abc.add(new JLabel("a:"));
abc.add(tfa);
abc.add(new JLabel("b:"));
abc.add(tfb);
abc.add(new JLabel("c:"));
abc.add(tfc);
//AusgabeBereich
JPanel ausgabe = new JPanel(new GridLayout(2, 3));
ausgabe.add(new JLabel("p [m]"));
ausgabe.add(new JLabel("q [m]"));
ausgabe.add(new JLabel("h [m]"));
ausgabe.add(P);
ausgabe.add(Q);
ausgabe.add(H);
P.setEditable(false);
Q.setEditable(false);
H.setEditable(false);
//Buttons mit Listenern
JPanel buttons = new JPanel(new FlowLayout());
JButton ok = new JButton("OK");
JButton cancel = new JButton("beenden");
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//Textfelder auslesen
TextfelderAuslesen();
//bei gueltiger Eingabe Höhe Berechnen
if(berechenbar){
berechnungPQ();
berechnungH();
P.setText(String.valueOf(p));
Q.setText(String.valueOf(q));
H.setText(String.valueOf(h));
sketch.update(vec);
sketch.repaint();
}else{
}
}
};
ok.addActionListener(al);
ActionListener beenden = new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
};
cancel.addActionListener(beenden);
buttons.add(ok);
buttons.add(cancel);
//Fensteraufbau
sketch.setPreferredSize(new Dimension(screen.height/2, screen.height/2));
jp.add(sketch);
eingabebereich.add(abc);
eingabebereich.add(ausgabe);
eingabebereich.add(buttons);
eingabebereich.setPreferredSize(new Dimension(screen.height/4, screen.height/4));
jp.add(eingabebereich);
f.add(jp);
f.setVisible(true);
}
}
public class Zeichnung extends JPanel{
public void paint(Graphics g){
zeichneDreieck(g);
}
private void zeichneDreieck(Graphics g){
berechneLaengen();
g.setColor(new Color(255,0,0));
g.drawLine(30, 30, ca, 30);
g.drawString("c", ca/2, 20);
g.drawLine(ca, 30, qa, ha);
g.drawString("a", (ca-pa/2), ha/2);
g.drawLine(qa, ha, 30, 30);
g.drawString("b", (qa/2), ha/2);
g.setColor(new Color(0,0,0));
g.drawLine(qa, ha, qa, 30);
g.drawString("h", qa+5, ha/2);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
zeichneDreieck(g);
}
For JPanel, override paintComponent() instead. As the first line, call the super method.
Call
yourFrame.invalidate();
yourFrame.validate();
yourFrame.repaint();
See more information about invalidate() and validate() here.
Per the documentation: The validate method is used to cause a container to lay out its subcomponents again. It should be invoked when this container's subcomponents are modified (added to or removed from the container, or layout-related information changed) after the container has been displayed.
Create a new method clear(Graphics g) in your Zeichnung class and clear all the lines from it by adding the body as:
super.paintComponent(g);
this.removeAll();
this.updateUI();
Call this method in your zeichneDreieck method at the first line.