Hi I've got a problem in the code below ( in method "append(String str)" mostly). I want to show messages received in HTML format (so I need to use JLabel).
Without setting tac.preferredSize here is what I get:
BUT it isn't working using long string without blank spaces:
such as "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".
If I set tac.preferredSize the height of the bubble isn't increasing:
How can I overcome these problems? (working on layout/sizes and not modifying input string)
Here's the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClientGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel label;
private JTextField tf;
private JPanel chatPanel;
private JScrollPane scroll;
ClientGUI() {
super("Chat Client");
label = new JLabel("You can write messages below:", SwingConstants.CENTER);
chatPanel = new JPanel();
tf = new JTextField("");
tf.setBackground(Color.WHITE);
tf.requestFocus();
tf.setVisible(true);
tf.addActionListener(this);
chatPanel.setLayout(new BoxLayout(chatPanel, BoxLayout.PAGE_AXIS));
chatPanel.add(Box.createVerticalGlue());
JPanel centerPanel = new JPanel(new GridLayout(1,1));
scroll = new JScrollPane();
scroll.setViewportView(chatPanel);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
centerPanel.add(scroll);
add(centerPanel, BorderLayout.CENTER);
JPanel southPanel = new JPanel(new BorderLayout());
JPanel writeChatPanel = new JPanel(new GridLayout(2,1));
writeChatPanel.add(label);
writeChatPanel.add(tf);
southPanel.add(writeChatPanel, BorderLayout.NORTH);
add(southPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(600, 600);
setVisible(true);
chatPanel.scrollRectToVisible(new Rectangle(chatPanel.getSize()));
}
void append(String str) {
LeftArrowBubble leftArrowBubble = new LeftArrowBubble();
leftArrowBubble.setMaximumSize(new Dimension(400,350));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(350,400));
//tac.setPreferredSize(new Dimension(350,50)); //<----------
System.out.println(str);
tac.setText("<html><body style='width: 350px; padding:15px;display:block;'>"+str+"</body></html>");
tac.setOpaque(false);
leftArrowBubble.add(tac, BorderLayout.NORTH);
chatPanel.add(leftArrowBubble);
chatPanel.add(Box.createRigidArea(new Dimension(0,5)));
Rectangle rect = chatPanel.getBounds();
Rectangle r2 = scroll.getViewport().getVisibleRect();
chatPanel.scrollRectToVisible(new Rectangle((int) rect.getWidth(),
(int) rect.getHeight(), (int) r2.getWidth(), (int) r2.getHeight()));
revalidate();
repaint();
}
public void actionPerformed(ActionEvent e) {
// just have to send the message
append(tf.getText());
tf.setText("");
return;
}
public static void main(String[] args) {
new ClientGUI();
}
}
And the bubble class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class LeftArrowBubble extends JPanel {
private static final long serialVersionUID = -5389178141802153305L;
public LeftArrowBubble() {
this.setLayout(new BoxLayout(this,BoxLayout.PAGE_AXIS));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D graphics2D = (Graphics2D) g;
RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHints(qualityHints);
graphics2D.setPaint(new Color(80, 150, 180));
int width = getWidth();
int height = getHeight();
GeneralPath path = new GeneralPath();
path.moveTo(5, 10);
path.curveTo(5, 10, 7, 5, 0, 0);
path.curveTo(0, 0, 12, 0, 12, 5);
path.curveTo(12, 5, 12, 0, 20, 0);
path.lineTo(width - 10, 0);
path.curveTo(width - 10, 0, width, 0, width, 10);
path.lineTo(width, height - 10);
path.curveTo(width, height - 10, width, height, width - 10, height);
path.lineTo(15, height);
path.curveTo(15, height, 5, height, 5, height - 10);
path.lineTo(5, 15);
path.closePath();
graphics2D.fill(path);
}
}
If you break up the words that are too long by adding spaces, I think most of your problems are solved. Some small changes to the dimensions of the leftArrowBubble and tac components would be useful as well.
You could replace the following lines in the append method:
leftArrowBubble.setMaximumSize(new Dimension(400,350));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(350,400));
//tac.setPreferredSize(new Dimension(350,50)); //<----------
System.out.println(str);
tac.setText("<html><body style='width:350px;padding:15px;display:block;'>"
+ str + "</body></html>");
by the following code (you can also take a look at Split string to equal length substrings in Java for more ways to split a string in equal parts):
leftArrowBubble.setMaximumSize(new Dimension(500, 500));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(450, 450));
//tac.setPreferredSize(new Dimension(350, 50)); //<----------
final int maximumSize = 56;
String textWithSeparators = "";
final StringTokenizer textTokenizer
= new StringTokenizer(str, " \t\n\r", true);
while (textTokenizer.hasMoreTokens()) {
final String part = textTokenizer.nextToken();
for (int beginIndex = 0; beginIndex < part.length();
beginIndex += maximumSize)
textWithSeparators += (beginIndex == 0 ? "" : " ")
+ part.substring(beginIndex,
Math.min(part.length(),
beginIndex + maximumSize));
}
System.out.println(textWithSeparators);
tac.setText("<html><body style='width:350px;padding:15px;display:block;'>"
+ textWithSeparators + "</body></html>");
The value for maximumSize could be calculated using font metrics (see How to get the correct String width from FontMetrics in JAVA for more information), but I've used a fixed value here for the sake of simplicity.
It would be nice to link the dimensions of leftArrowBubble, tac, and the width in the html string, like:
final int size = 500;
leftArrowBubble.setMaximumSize(new Dimension(size, size));
JLabel tac = new JLabel();
tac.setMaximumSize(new Dimension(size - 50, size - 50));
// [...]
tac.setText("<html><body style='width:" + (size - 150)
+ "px;padding:15px;display:block;'>"
+ textWithSeparators + "</body></html>");
Related
The idea behind the code is a simple multiplying game where it generates 2 numbers and I have to input the corret answer.
Basically, my question(s) is(are):
When I do operacao.setOpaque(false); it does nothing, or at least not what I'd expect it to do (http://puu.sh/pyVcE/813aa1843a.png - shouldn't the grey area be pink, since the background is pink?). Same happens with JLabels, the setOpaque(false) leaves a grey background behind the (in this case) numbers.
I have that last commented section because I saw someone around here saying to alter the paint method, and it did work, but caused some weird issues (painted over everything when I started the console, only the JTextField would be clear), and then I "fixed" it with the setOpacity(1); setBackground(pink); - is this a proper way of doing it?
public class Frame extends JFrame {
private JPanel panel, mensagem, operacao;
private JTextArea sucesso;
private JLabel numero1, numero2;
private JTextField resposta;
private Color pink = new Color(255, 213, 224);
//more vars
public Frame() {
super("Jogo de Multiplicar!");
setOpacity(1);
setBackground(pink);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(300, 200);
panel = new JPanel();
mensagem = new JPanel();
operacao = new JPanel();
mensagem.setLayout(new FlowLayout(FlowLayout.CENTER));
operacao.setLayout(new FlowLayout(FlowLayout.CENTER));
sucesso = new JTextArea();
sucesso.setEditable(false);
sucesso.setOpaque(false);
sucesso.setFont(minhaFont2);
Random randomGen = new Random();
while (random1 == 0)
random1 = randomGen.nextInt(10);
while (random2 == 0)
random2 = randomGen.nextInt(10);
res = random1 * random2;
numero1 = new JLabel();
numero2 = new JLabel();
numero1.setText(random1 + " *");
numero2.setText(random2 + " =");
numero1.setOpaque(false);
numero1.setFont(minhaFont);
numero2.setFont(minhaFont);
resposta = new JTextField(2);
resposta.addActionListener(new MinhaAcao());
resposta.setFont(minhaFont);
operacao.add(numero1);
operacao.add(numero2);
operacao.add(resposta);
mensagem.add(sucesso);
operacao.setOpaque(true);
operacao.setBackground(pink);
mensagem.setOpaque(true);
mensagem.setBackground(pink);
//add(panel, BorderLayout.NORTH);
add(operacao);
add(mensagem, BorderLayout.SOUTH);
}/*
public void paint(Graphics g) {
g.setColor(pink);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}*/
You need to textfield to be pink. You may have to do this.
resposta.setOpaque(false);
I have refactored your code like below.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Frame extends JFrame {
private JPanel panel, mensagem, operacao;
private JTextArea sucesso;
private JLabel numero1, numero2;
private JTextField resposta;
private Color pink = new Color(255, 213, 224);
//more vars
public Frame() {
super("Jogo de Multiplicar!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(300, 200);
getContentPane().setBackground(pink);
panel = new TransperantPanel();
mensagem = new TransperantPanel();
operacao = new TransperantPanel();
mensagem.setLayout(new FlowLayout(FlowLayout.CENTER));
operacao.setLayout(new FlowLayout(FlowLayout.CENTER));
sucesso = new JTextArea();
sucesso.setEditable(false);
Random randomGen = new Random();
int random1 =0 , random2 = 0;
while (random1 == 0)
random1 = randomGen.nextInt(10);
while (random2 == 0)
random2 = randomGen.nextInt(10);
int res = random1 * random2;
numero1 = new JLabel();
numero2 = new JLabel();
numero1.setText(random1 + " *");
numero2.setText(random2 + " =");
resposta = new JTextField(2);
resposta.setOpaque(false);
resposta.addActionListener(new MinhaAcao());
numero1.setFont(minhaFont);
numero2.setFont(minhaFont);
resposta.setFont(minhaFont);
operacao.add(numero1);
operacao.add(numero2);
operacao.add(resposta);
mensagem.add(sucesso);
add(operacao);
add(mensagem, BorderLayout.SOUTH);
}
public static void main(String[] args){
Frame f = new Frame();
f.setVisible(true);
}
class TransperantPanel extends JPanel {
public TransperantPanel() {
setOpaque(false);
}
}
}
What i have done is
Setting background to contentPane of the frame.
Created a transparent panel(setting Opaque of the panel to false).
Setting JTextfield's Opaque to false.
I have a problem when i'm trying to use a Timer Object and a repaint() when it is called.
Here's my Window Class :
import javax.swing.*;
import java.awt.*;
public class Window extends JFrame{
Panel pan = new Panel();
JPanel container, north,south, west;
JButton ip,print,cancel,ok;
JTextArea timeStep;
JLabel legend;
double temperature=0.0;
public static void main(String[] args) {
new Window();
}
public Window()
{
System.out.println("je suis là");
this.setSize(700,400);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setTitle("Assignment2 - CPU temperature");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new JPanel(new BorderLayout());
north = new JPanel();
ip = new JButton ("New");
north.add(ip);
north.add(new JLabel("Time Step: "));
timeStep = new JTextArea("10",1,5);
north.add(timeStep);
print = new JButton ("Print");
north.add(print);
south = new JPanel();
legend = new JLabel("Legends are here");
south.add(legend);
west = new JPanel();
JLabel temp = new JLabel("°C");
west.add(temp);
container.add(north, BorderLayout.NORTH);
container.add(west,BorderLayout.WEST);
container.add(pan, BorderLayout.CENTER);
container.add(south, BorderLayout.SOUTH);
this.setContentPane(container);
this.setVisible(true);
}
}
And Here's my Panel class :
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Panel extends JPanel implements ActionListener {
Timer chrono = new Timer(1000,this);
int i = 0;
int t = 10;
public Panel()
{
super();
chrono.start();
}
public void paintComponent(Graphics g)
{
g.drawLine(20, 20, 20, this.getHeight()-50);
g.drawLine(20, this.getHeight()-50, this.getWidth()-50, this.getHeight()-50);
g.drawLine(20, 20, 15, 35);
g.drawLine(20, 20, 25, 35);
g.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-45);
g.drawLine(this.getWidth()-50, this.getHeight()-50, this.getWidth()-65, this.getHeight()-55);
g.drawLine(20+t, this.getHeight()-50-i, 20+t, this.getHeight()-50);
}
#Override
public void actionPerformed(ActionEvent e) {
/*i = (int)(50+(20 + (Math.random() * (60 - 20))));
t = t+10;
repaint();
System.out.println("chrono");*/
}
}
Here's how it is like when the repaint() function isn't called :
GUI:
And Finally here's how it looks like when repaint() function is called :
GUI bug:
It seems that all of my JPanels are repainting only once and then everything works...
Any thought?
The problem is that you never paint over what's drawn before. JPanel by default is supposed to be opaque, meaning that it will draw over its entire area each redraw, freeing the frame to not have to worry about cleaning up that space. However, you're removing that functionality from the JPanel.
In your paintComponent method, add this at the top:
super.paintComponent(g);
This will let the JPanel correctly redraw itself (by calling its own paintComponent method), so that you can do your drawing over a clean slate.
In response to your comment, the best way to keep the old lines is to keep track of each line to draw, and repaint them all each time. To do that, you would need to replace t and i with lists, which would look something like this:
List<Integer> is = new ArrayList<>();
List<Integer> ts = new ArrayList<>();
int lastT = 0;
And then add to those instead of simply setting the value:
int i = (int)(50 + (20 + (Math.random() * (60 - 20))));
lastT += 10;
is.add(i);
ts.add(lastT);
repaint();
And finally, loop over each value:
for(int j = 0; i < is.size() && ts.size(); i++){
int i = is.get(j);
int t = ts.get(j);
g.drawLine(20 + t, this.getHeight() - 50 - i,
20 + t, this.getHeight() - 50);
}
I haven't tested the above code, so it may have some mistakes, but it should be the right idea.
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);
}
So, I'm trying to make a program where you can input the quadratic formula (ax^2+bx+c) via sliders. Then it draws a graph as you adjust for A, B, and C.
Issues:
I want the stuff I wrote in super paint and the sliders to be in one place.
The sliders are in place when I run it. There's space with the correct background where I want my graph in the panel but no actual graph.
Here's my driver class:
import java.awt.*;
import javax.swing.*;
public class quadraticslider
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Quadratic Slider");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new pp109quadraticpanel());
frame.pack();
frame.setVisible(true);
}
}
Here's the panel class:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class quadraticpanel extends JPanel
{
private JPanel controls, graphPanel;
private JSlider ASlider, BSlider, CSlider;
private JLabel ALabel, BLabel, CLabel;
double A, B, C, x,Y;
//
//SLIDERS YO
//
public quadraticpanel()
{
ASlider = new JSlider (JSlider.HORIZONTAL, 0, 255, 0);
ASlider.setMajorTickSpacing (50);
ASlider.setMinorTickSpacing (10);
ASlider.setPaintTicks (true);
ASlider.setPaintLabels (true);
ASlider.setAlignmentX (Component.LEFT_ALIGNMENT);
BSlider = new JSlider (JSlider.HORIZONTAL, 0, 255, 0);
BSlider.setMajorTickSpacing (50);
BSlider.setMinorTickSpacing (10);
BSlider.setPaintTicks (true);
BSlider.setPaintLabels (true);
BSlider.setAlignmentX (Component.LEFT_ALIGNMENT);
CSlider = new JSlider (JSlider.HORIZONTAL, 0, 255, 0);
CSlider.setMajorTickSpacing (50);
CSlider.setMinorTickSpacing (10);
CSlider.setPaintTicks (true);
CSlider.setPaintLabels (true);
CSlider.setAlignmentX (Component.LEFT_ALIGNMENT);
SliderListener listener = new SliderListener();
ASlider.addChangeListener (listener);
BSlider.addChangeListener (listener);
CSlider.addChangeListener (listener);
ALabel = new JLabel ("a: 0");
ALabel.setAlignmentX (Component.LEFT_ALIGNMENT);
BLabel = new JLabel ("b: 0");
BLabel.setAlignmentX (Component.LEFT_ALIGNMENT);
CLabel = new JLabel ("c: 0");
CLabel.setAlignmentX (Component.LEFT_ALIGNMENT);
controls = new JPanel();
BoxLayout layout = new BoxLayout (controls, BoxLayout.Y_AXIS);
controls.setLayout (layout);
controls.add (ALabel);
controls.add (ASlider);
controls.add (Box.createRigidArea (new Dimension (0, 20)));
controls.add (BLabel);
controls.add (BSlider);
controls.add (Box.createRigidArea (new Dimension (0, 20)));
controls.add (CLabel);
controls.add (CSlider);
graphPanel = new JPanel();
graphPanel.setPreferredSize (new Dimension (500, 500));
graphPanel.setBackground (Color.white);
add (controls);
add (graphPanel);
}
//Here I'm taking the equation, running it through -10 to 10
//It takes the doubles from the equation, converts
//it to int then draws the quadratic formula in dots.
public void paintComponent(Graphics page)
{
super.paintComponent (page);
for ( x=-10; x <= 10; x++)
{
Y = (A*(Math.pow(x,2)))+(B*x)+(C);
int g = (int)Math.round(x);
int h = (int)Math.round(Y);
page.setColor (Color.black);
page.fillOval (g, h, 1, 1);
}
}
public class SliderListener implements ChangeListener
{
///
///Reads the user input via slider.
///
public void stateChanged (ChangeEvent event)
{
A = ASlider.getValue();
B = BSlider.getValue();
C = CSlider.getValue();
ALabel.setText ("a: " + A);
BLabel.setText ("b: " + B);
CLabel.setText ("c: " + C);
}
}
}
These examples using JFreeChart may be of interest. As shown here, you can animate the rendering using SwingWorker, and this example updates a chart using a JSlider.
Addendum: This variation of your code may guide you going forward. Note,
Override relevant methods in your graphPanel.
Scale and invert coordinates, as shown here.
Consider JSpinner for fractional values.
Use constants for consistency.
Use common naming conventions for clarity.
See also Initial Threads.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/** #see https://stackoverflow.com/a/20556929/230513 */
public class QuadraticSlider {
private static final int N = 500;
private static final int A = 1;
private static final int B = 0;
private static final int C = 0;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Quadratic Slider");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new QuadraticPanel());
frame.pack();
frame.setVisible(true);
}
});
}
private static class QuadraticPanel extends JPanel {
private Box controls;
private JPanel graphPanel;
private JSlider aSlider, bSlider, cSlider;
private JLabel aLabel, bLabel, cLabel;
double a, b, c, x, y;
public QuadraticPanel() {
aSlider = new JSlider(JSlider.HORIZONTAL, -25, 25, A);
aSlider.setMajorTickSpacing(10);
aSlider.setMinorTickSpacing(5);
aSlider.setPaintTicks(true);
aSlider.setPaintLabels(true);
aSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
bSlider = new JSlider(JSlider.HORIZONTAL, -10, 10, B);
bSlider.setMajorTickSpacing(5);
bSlider.setMinorTickSpacing(1);
bSlider.setPaintTicks(true);
bSlider.setPaintLabels(true);
bSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
cSlider = new JSlider(JSlider.HORIZONTAL, -100, 100, C);
cSlider.setMajorTickSpacing(50);
cSlider.setMinorTickSpacing(10);
cSlider.setPaintTicks(true);
cSlider.setPaintLabels(true);
cSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
SliderListener listener = new SliderListener();
aSlider.addChangeListener(listener);
bSlider.addChangeListener(listener);
cSlider.addChangeListener(listener);
aLabel = new JLabel("a: 0");
bLabel = new JLabel("b: 0");
cLabel = new JLabel("c: 0");
controls = new Box(BoxLayout.Y_AXIS);
controls.add(aLabel);
controls.add(aSlider);
controls.add(Box.createRigidArea(new Dimension(0, 20)));
controls.add(bLabel);
controls.add(bSlider);
controls.add(Box.createRigidArea(new Dimension(0, 20)));
controls.add(cLabel);
controls.add(cSlider);
graphPanel = new JPanel() {
private static final int SCALE = 5;
#Override
public Dimension getPreferredSize() {
return new Dimension(N, N);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (x = -10; x <= 10; x++) {
y = a * x * x + b * x + c;
g.setColor(Color.black);
int w = (int) (x * SCALE) + N / 2;
int h = (int) (-y * SCALE) + N / 2;
g.fillOval(w, h, 5, 5);
}
}
};
graphPanel.setBackground(Color.white);
add(controls);
add(graphPanel);
listener.stateChanged(null);
}
class SliderListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent event) {
a = aSlider.getValue() / 5d;
b = bSlider.getValue();
c = cSlider.getValue();
aLabel.setText("a: " + a);
bLabel.setText("b: " + b);
cLabel.setText("c: " + c);
repaint();
}
}
}
}
_"error: possible loss of precision Y = (A*(Math.pow(x,2)))+(B*x)+(C); ^ required: int found: double"_
All your int variables int A, B, C, x,Y;. Make them doubles. double A, B, C, x,Y;
I modified the code so that it solves for x given a b and c. Then plugs x back in and solves for y. I'm still not getting it to draw though. I also took out the loop since the sliders are setting the a b and c values which lead to x. Anyone know why it won't draw?
package quadraticslider;
import java.awt.*;
import javax.swing.*;
public class quadraticslider
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Quadratic Slider");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new quadraticpanel());
frame.pack();
frame.setVisible(true);
}
}
package quadraticslider;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class quadraticpanel extends JPanel
{
private JPanel controls, graphPanel;
private JSlider ASlider, BSlider, CSlider;
private JLabel ALabel, BLabel, CLabel;
double A, B, C, x,Y;
public quadraticpanel()
{
ASlider = new JSlider (JSlider.HORIZONTAL, -25, 25, 0);
ASlider.setMajorTickSpacing (50);
ASlider.setMinorTickSpacing (10);
ASlider.setPaintTicks (true);
ASlider.setPaintLabels (true);
ASlider.setAlignmentX (Component.LEFT_ALIGNMENT);
BSlider = new JSlider (JSlider.HORIZONTAL, -25, 25, 0);
BSlider.setMajorTickSpacing (50);
BSlider.setMinorTickSpacing (10);
BSlider.setPaintTicks (true);
BSlider.setPaintLabels (true);
BSlider.setAlignmentX (Component.LEFT_ALIGNMENT);
CSlider = new JSlider (JSlider.HORIZONTAL, -25, 25, 0);
CSlider.setMajorTickSpacing (50);
CSlider.setMinorTickSpacing (10);
CSlider.setPaintTicks (true);
CSlider.setPaintLabels (true);
CSlider.setAlignmentX (Component.LEFT_ALIGNMENT);
SliderListener listener = new SliderListener();
ASlider.addChangeListener (listener);
BSlider.addChangeListener (listener);
CSlider.addChangeListener (listener);
ALabel = new JLabel ("a: 0");
ALabel.setAlignmentX (Component.LEFT_ALIGNMENT);
BLabel = new JLabel ("b: 0");
BLabel.setAlignmentX (Component.LEFT_ALIGNMENT);
CLabel = new JLabel ("c: 0");
CLabel.setAlignmentX (Component.LEFT_ALIGNMENT);
controls = new JPanel();
BoxLayout layout = new BoxLayout (controls, BoxLayout.Y_AXIS);
controls.setLayout (layout);
controls.add (ALabel);
controls.add (ASlider);
controls.add (Box.createRigidArea (new Dimension (0, 20)));
controls.add (BLabel);
controls.add (BSlider);
controls.add (Box.createRigidArea (new Dimension (0, 20)));
controls.add (CLabel);
controls.add (CSlider);
graphPanel = new JPanel();
graphPanel.setPreferredSize (new Dimension (500, 500));
graphPanel.setBackground (Color.white);
add (controls);
add (graphPanel);
}
public void paintComponent(Graphics page)
{
super.paintComponent (page);
x = (-B + (Math.sqrt((B*B - ((4 * A * C))))))/ (2 * A);
Y = (A*(Math.pow(x,2)))+(B*x)+(C);
int g = (int)Math.round(x);
int h = (int)Math.round(Y);
page.setColor (Color.black);
page.drawOval (g, h, 1, 1);
}
public class SliderListener implements ChangeListener
{
///
///Reads the user input via slider.
///
public void stateChanged (ChangeEvent event)
{
A = ASlider.getValue();
B = BSlider.getValue();
C = CSlider.getValue();
ALabel.setText ("a: " + A);
BLabel.setText ("b: " + B);
CLabel.setText ("c: " + C);
}
}
}
I am working on a project where I have to create an image manager program in Java. The program will have the following features in it: Program should take image from the user as input. Then it should display the image in panel(1), and in panel(2) it should give the user an options of changing width, height, hgap, vgap, top margin and left margin of the image with an 'OK' button at the end including an 'action listener' feature. Using the above mentioned features we will get the grids on the image. Now if the user clicks on the particular grid then that particular image should get extracted into a folder.
I am attaching the program which we have done so far.
The difficulties we are facing are: we are not able to insert a JScrollPane for the image. As well as we are unaware of how to add action listeners to the grids so that we can extract that particular image.
package project_image_manager_imp_files;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
class SidePanel1 extends JPanel implements ActionListener {
JTextField top_margin = new JTextField(10);
JTextField left_margin = new JTextField(10);
JTextField Width = new JTextField(10);
JTextField Height = new JTextField(10);
JTextField Vgap = new JTextField(10);
JTextField Hgap = new JTextField(10);
JLabel j1 = new JLabel("Top margin");
JLabel j2 = new JLabel("Left margin");
JLabel j3 = new JLabel("Width");
JLabel j4 = new JLabel("Height");
JLabel j5 = new JLabel("Vertical gap");
JLabel j6 = new JLabel("Horizontal gap");
JButton b = new JButton("OK");
public SidePanel1() {
this.setBackground(Color.black);
Dimension d1 = new Dimension(1000, 1000);
this.setMaximumSize(d1);
this.setPreferredSize(d1);
JPanel p = new JPanel();
JScrollPane vertical = new JScrollPane();
vertical.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(vertical);
vertical.setVerticalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(vertical);
//showCoo.build(c);
//c.add(p);
//p.setOpaque(false);
//t1.addActionListener(new JTextFieldEventClass() );
//b.addActionListener(new JTextFieldEventClass() );
// String s=t3.getText();
//int c=Integer.parseInt(s);
p.add(j1);
p.add(top_margin);
p.add(j2);
p.add(left_margin);
p.add(j3);
p.add(Width);
p.add(j4);
p.add(Height);
p.add(j5);
p.add(Vgap);
p.add(j6);
p.add(Hgap);
p.add(b);
p.setLayout(new GridLayout(7, 2));
b.addActionListener(this);
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(1, 2));
frame.setBounds(200, 200, 600, 400);
frame.setTitle("Hello World Test");
frame.setResizable(true);
//frame.setSize (500, 300);
Container c = frame.getContentPane();
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.WEST);
frame.add(p, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setResizable(true);
}
int height;
int width;
int hgap;
int vgap;
int tm;
int lm;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(Toolkit.getDefaultToolkit().getImage("images1.jpg"), 0, 0, this);
Graphics2D g2d = (Graphics2D) g.create();
//File f=new File("images1.jpg");
//BufferedImage im=ImageIO.read(f);
int frame_width = getWidth();
int frame_height = getHeight();
for (int j = 0; j < frame_height; j++) {
int y = tm + (height * j) + (vgap * j);
for (int i = 0; i < frame_width; i++) {
int x = lm + (width * i) + (hgap * i);
g.drawRect(x, y, width, height);
}
}
}
public static void main(String[] argv) {
//static JScrollBar scrollbar;
SidePanel1 panel = new SidePanel1();
panel.setLayout(new FlowLayout());
//scrollbar = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//panel.add(scrollbar);
try {
while (true) {
Thread.sleep(100);
///.out.println("("+MouseInfo.getPointerInfo().getLocation().x+", "+MouseInfo.getPointerInfo().getLocation().y+")");
}
} catch (InterruptedException e) {}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
width = Integer.parseInt(Width.getText());
height = Integer.parseInt(Height.getText());
hgap = Integer.parseInt(Hgap.getText());
vgap = Integer.parseInt(Vgap.getText());
lm = Integer.parseInt(left_margin.getText());
tm = Integer.parseInt(top_margin.getText());
repaint();
}
}