Java Rendering Artifacts When Adding Buttons To Semi-Transparent JPanel - java

I have a problem. I am trying to create "alert" component that I can display in a JFrame. This alert has a semi-transparent background (70% opacity, white) with any trivial amount of JButtons on it. The background itself has rounded corners, and thus I made a custom component.
When rendering this alert, artifacts appear: no alert-background is rendered on the button that is initially selected. When moving my mouse across the buttons, it looks like the text of the buttons is being drawn in two places for no reason.
Screenshots of the artifacts (top = initial render, bottom = moving mouse around):
Code that causes these problems:
public class Test {
public static void main(String[] args) {
MyRoundedTransparentBackground background = new MyRoundedTransparentBackground();
background.setSize(200, 200);
background.setLocation(100, 100);
background.setLayout(new GridBagLayout());
JPanel spacer = new JPanel();
spacer.setBackground(new Color(0, 0, 0, 0));
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = 1;
c.gridheight = 1;
c.weighty = 1;
background.add(spacer, c);
JButton button1 = new JButton("Hi there");
JButton button2 = new JButton("Bye ...");
button1.setBackground(new Color(0, 0, 0, 0));
button1.setFocusPainted(false);
button1.setBorderPainted(false);
button2.setBackground(new Color(0, 0, 0, 0));
button2.setFocusPainted(false);
button2.setBorderPainted(false);
c.weighty = 0;
c.gridy = 1;
background.add(button1, c);
c.gridx = 1;
background.add(button2, c);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
frame.setLocation(2000, 100);
frame.setLayout(null);
frame.getContentPane().setBackground(Color.red);
frame.add(background);
frame.setVisible(true);
}
private static class MyRoundedTransparentBackground extends JComponent {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(1f, 1f, 1f, 0.7f));
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}
}
Can someone help me find out what the issue is, and give a potential solution to achieve the desired behavior?

Related

AbstractBorder paints over JTabbedPane

So I'm using Swing and trying to use a JTabbedPane to encompass several JPanels with JScrollPanes to scroll through a list of JPanels. The issue that arises is whenever I change tabs, among other things, the custom border function I have in the JPanels inside the scroll pane results in the components painting over the top of the JTabbedPane header and I have no idea of how to fix this problem: AbstractBorder paints over JTabbedPane header. I have provided code that mimics what I'm trying to do below. To replicate the issue, scroll down some on one tab until one of the outlined panels is halfway visible at the top. Then, switch to a different tab and then back. Then, scroll some more and the issue will present itself at the top of the JTabbedPane
public class Example extends JFrame {
private final JTabbedPane tabbedPane;
public Example() {
setTitle("MIN Example");
setSize(600, 700);
setLayout(new BorderLayout());
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.BLACK);
setExtendedState(JFrame.MAXIMIZED_BOTH);
tabbedPane = new JTabbedPane();
tabbedPane.setBorder(BorderFactory.createEmptyBorder());
tabbedPane.setFocusable(false);
add(tabbedPane, BorderLayout.CENTER);
createTabs();
setVisible(true);
}
private void createTabs() {
// Get the list of guilds
List<String> tabs = new ArrayList<>(Arrays.asList("Tab 1", "Tab 2", "Tab 3"));
// Iterate through the tabs and create the tab
for (String tab : tabs) {
// Initialize the list JPanel and formatting
JPanel panelList = new JPanel();
panelList.setLayout(new GridBagLayout());
// House the list panel inside a JScrollPane
JScrollPane listScroll = new JScrollPane(panelList);
listScroll.setBorder(BorderFactory.createEmptyBorder());
// Create tab and formatting
tabbedPane.addTab(tab, listScroll);
populateList(panelList);
}
}
private void populateList(JPanel tab) {
// Create GBC for formatting
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
// Remove all components from the JPanel
tab.removeAll();
// Add filler JPanel
JPanel filler = new JPanel();
filler.setOpaque(false);
tab.add(filler, gbc);
// Update GBC constraints
gbc.insets = new Insets(10, 10, 0, 10);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = GridBagConstraints.RELATIVE;
// Go through the tabs and add JPanels
for (int i = 10; i >= 0; i--) {
JPanel tempPanel = new JPanel();
tempPanel.setBorder(new RoundedBorder(Color.BLACK, 6, 16));
tab.add(tempPanel, gbc, 0);
tempPanel.setPreferredSize(new Dimension(0, 100));
}
// Refresh the console to display updated lists
validate();
repaint();
}
}
public class RoundedBorder extends AbstractBorder {
private final Color color;
private final int thickness;
private final int radii;
private final Insets insets;
private final BasicStroke stroke;
private final int strokePad;
RenderingHints hints;
/**
* Creates the rounded border
*
* #param color The color of the border outline
* #param thickness The thickness of the border outline
* #param radii The radius of the rounded border
*/
public RoundedBorder(Color color, int thickness, int radii) {
this.thickness = thickness;
this.radii = radii;
this.color = color;
stroke = new BasicStroke(thickness);
strokePad = thickness / 2;
hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int pad = radii + strokePad;
int bottomPad = pad + strokePad;
insets = new Insets(pad, pad, bottomPad, pad);
}
#Override
public Insets getBorderInsets(Component c) {
return insets;
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g;
int bottomLineY = height - thickness;
RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(strokePad, strokePad, width - thickness, bottomLineY, radii, radii);
Area area = new Area(bubble);
g2.setRenderingHints(hints);
// Paint the background color of the parent
Component parent = c.getParent();
if (parent != null) {
Color background = parent.getBackground();
Rectangle rect = new Rectangle(0,0,width, height);
Area borderRegion = new Area(rect);
borderRegion.subtract(area);
g2.setClip(borderRegion);
g2.setColor(background);
g2.fillRect(0, 0, width, height);
g2.setClip(null);
}
g2.setColor(color);
g2.setStroke(stroke);
g2.draw(area);
}
}
The only things I have tried to do to fix this issue was changing the order of adding the JTabbedPane (Add before the tabs were populated with panels) to no avail. Help would be greatly appreciated, thank you.
In the future, an MRE should include:
the import statements
the main() method
In the original code the "clip" of the Graphics is being set to null so the entire Rectangle of the panel appears to be painted.
I modified the painting of the parent to use a separate Graphics object so the original "clip" area is not affected:
// Paint the background color of the parent
Component parent = c.getParent();
if (parent != null) {
Graphics2D g2d = (Graphics2D)g2.create();
Color background = parent.getBackground();
//Rectangle rect = new Rectangle(0, 0, width, height);
Rectangle rect = g2d.getClip().getBounds();
Area borderRegion = new Area(rect);
borderRegion.subtract(area);
g2d.setClip(borderRegion);
g2d.setColor(background);
g2d.fillRect(0, 0, width, height);
g2d.dispose();
}

How to put a JPanel with 2DGraphics on a JFrame (same class)

I have a class that extends JFrame and I would like to add two JPanels to that JFrame: a text panel and a graphics panel. My text panel is a panel containing a label with text. My graphics panel will contain a graph (created using 2DGraphics). I'm adding the graphic panel to the left side (0,0) and the text panel to right side (1,0) using a gridbaglayout method. However, the graphic panel won't show up in the frame. I have tried numerous methods to try to get the panel to show up with no success.
import java.awt.*;
import javax.swing.*;
public class GraphicsTest extends JFrame {
private final JPanel textPanel;
private final JLabel textLabel;
public GraphicsTest() {
textPanel = new JPanel(new BorderLayout());
textLabel = new JLabel("Home label");
this.setBounds(180, 112, 1080, 675);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new GridBagLayout());
textPanel.add(textLabel, BorderLayout.NORTH);
addComponent(this, new GraphicPanel(), 0, 0, 1, 1, GridBagConstraints.CENTER);
addComponent(this, textPanel, 1, 0, 1, 1, GridBagConstraints.CENTER);
this.setVisible(true);
}
public class GraphicPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void paintComponents(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
// drawing lots of shapes and lines, removed for readibility
}
}
public void addComponent(JFrame frame, JComponent component, int x, int y, int width, int height, int align) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = x;
c.gridy = y;
c.gridwidth = width;
c.gridheight = height;
c.weightx = 100.0;
c.weighty = 100.0;
c.insets = new Insets(5, 0, 5, 0);
c.anchor = align;
c.fill = GridBagConstraints.NONE;
frame.add(component, c);
}
public static void main(String[] args) {
GraphicsTest gui = new GraphicsTest();
}
}
Works fine for me when I use a size like (200, 200).
GridbagLayout works such that if a component can't be displayed at its preferred size, then it will be displayed at its minimum size, which would be (0, 0).
So whether (700, 700) works will depend on your screen resolution. It also works at (700, 600) for my screen.
I question if you want to use a GridBadLayout. Maybe just use a BorderLayout. The custom painting panel would go in the CENTER so it will grow/shrink as the frame size changes. The other panel would go to the LINE_END, so it will remain at a fixed size.

Bug of Transparent JCheckBox in a JPanel? [duplicate]

This question already has answers here:
Black square showing when adding a .GIF on JPanel
(2 answers)
Closed 7 years ago.
Here are my codes for adding the new component:
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (!todoListInput.getText().equals("")) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel.setBackground(new Color(213, 134, 145, 55));
JCheckBox checkBox = new JCheckBox("");
checkBox.setOpaque(false);
checkBox.setForeground(Color.WHITE);
//checkBox.setBorder(line);
panel.add(checkBox);
Border border = new LineBorder(Color.GRAY, 1, true);
Border margin = new EmptyBorder(10,10,10,10);
panel.setBorder(new CompoundBorder(margin, border));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainList.add(panel, gbc, 0);
validate();
repaint();
todoListInput.setText("");
}
}
});
My problem is that when I do an "onmouseover" action to the checkbox, part of the the whole jFrame will be appeared behind the checkbox
I found that this only appear when I do checkBox.setOpaque(false) or checkBox.setBackground(new Color(122,122,122,55)).
May I know what is the problem of my code?
panel.setBackground(new Color(213, 134, 145, 55));
The problem is your panel is using a transparent background and you are breaking the painting contract between a component. An opaque component needs to repaint the entire background (with an opaque color), however because of the transparency you are getting painting artifacts.
Check out Background With Transparency for more information and a couple of solutions.
The basic solution is:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false);
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);
However, the link also provides a reusable solution so you don't need to use custom painting on every component that has a transparent background.

Fit the component in the container by width in Swing

I have problem with creating own swing component. I want to create component that will render some image and it will fit current window (or container) size proportionally.
The problem is that I cant know real available space for component in container (without insents, borders, may be something else...).
This example shows the problem:
public class Main
{
static class MyComponent extends JComponent
{
#Override
public Dimension getPreferredSize()
{
if(isShowing())
{
int width = getParent().getSize().width - 4;
Dimension dimension = new Dimension(width, (int)(width / 0.8));
System.out.println(dimension);
return dimension;
}
return super.getPreferredSize();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.fillOval(0, 0, getWidth(), getHeight());
}
}
public static void main(String... args)
{
JFrame frame = new JFrame("Test");
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(Color.DARK_GRAY);
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(2, 2, 2, 2);
c.gridx = c.gridy = 0;
panel.add(new MyComponent(), c);
c.gridy++;
panel.add(new MyComponent(), c);
frame.add(new JScrollPane(panel));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
}
If you remove 4 (left & right from insets) from getParent().getSize().width - 4 expression and launch, you will see that component(s) will increase its size infinitely.
In the above code I get full width of container, but I need available width so that component will not trigger container to resize again and again.
Or is there another way to fit component normally?

Java buttons on top of graphics in a GUI issue

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);
}

Categories