I'm trying to make a solved sudoku puzzle show up in a window with 81 boxes. I did this:
import java.awt.GridLayout;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GraphicSolver extends JFrame {
GraphicSolver(int[][] spelplan) {
Panel panel = new Panel(new GridLayout(9,9));
for(int i=9;i<9;i++){
for(int x=0;x<9;x++){
panel.add(new JLabel(""+spelplan[i][x]));
}
}
Frame frame = new Frame();
frame.add(panel);
frame.setVisible(true);
}
}
However, it only gives me an empty window without any numbers. I'd be pleased if someone could point me in the right direction.
The outer loop should start at zero:
for(int i=0;i<9;i++){
You seem to have two Frames. 1 is the JFrame (the class GrpahicSolver itself) and the other a frame that you are creating within it.
I suggest you replace frame.addPanel() with this.addPanel() and it should work.
Try calling frame.pack (), this will pack all the components into the frame to be displayed after computing the correct size with the panels. Also, follow the fix suggested by #trashgod above will solve the fact that no panels were added, and the fix by #Ashkan Aryan will make your code a bit more reasonable (although it should work without it, but then there is no point in inheriting from JFrame).
The code below works for me:
GraphicSolver(int[][] spelplan) {
Panel panel = new Panel(new GridLayout(9,9));
for(int i=0;i<9;i++){
for(int x=0;x<9;x++){
panel.add(new JLabel(""+spelplan[i][x]));
}
}
this.add(panel);
this.pack ();
this.setVisible(true);
}
import java.awt.GridLayout;
import javax.swing.*;
public class GraphicSolver {
GraphicSolver(int[][] spelplan) {
// presumes each array 'row' is the same length
JPanel panel = new JPanel(new GridLayout(
spelplan.length,
spelplan[0].length,
8,
4));
for(int i=0;i<spelplan.length;i++){
for(int x=0;x<spelplan[i].length;x++){
panel.add(new JLabel(""+spelplan[i][x]));
}
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int[][] plan = new int[4][7];
for (int x=0; x<plan.length; x++) {
for (int y=0; y<plan[x].length; y++) {
plan[x][y] = (x*10)+y;
}
}
new GraphicSolver(plan);
}
});
}
}
Related
I am developing a simple application, and am currently working on the gui design using Swing. In my program I have a JPanel which I would like to have a background color black like so:
JPanel playerPanel = new JPanel();
playerPanel.setOpaque(true);
playerPanel.setBackground(Color.BLACK);
This code works fine. However, the problem is when I assign a Layout Manager to the panel:
JPanel playerPanel = new JPanel();
playerPanel.setOpaque(true);
playerPanel.setBackground(Color.BLACK);
playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.PAGE_AXIS));
For some reason, this makes the black color of the panel go away. This happens no matter where I place the .setLayout(...) command, before or after the .setBackground(...) and .setOpaque(true).
Why is this, and how do I work around this? How do I keep a black JPanel that uses a BoxLayout manager?
Verify that your panel's content is not obscuring the altered background. Resize the example below, which I've artificially enlarged, to see the effect.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/57785802/230513
*/
public class BoxTest {
public static final Random random = new Random();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new BoxTest().create();
}
});
}
void create() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.BLACK);
panel.add(Box.createVerticalGlue());
for (int i = 0; i < 4; i++) {
panel.add(new VariablePanel());
panel.add(Box.createVerticalGlue());
}
JFrame f = new JFrame("BoxTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
f.setSize(f.getWidth(), f.getHeight() + 64);
}
}
/**
* A VariablePanel has a label showing its current size,
* as well as a variable number of text items.
*/
class VariablePanel extends JPanel {
private static final String text =
"Sed ut perspiciatis unde omnis iste natus error sit.";
private final JLabel sizeLabel = new JLabel("Size:");
public VariablePanel() {
this.setLayout(new GridLayout(0, 1));
this.add(sizeLabel);
int count = BoxTest.random.nextInt(5) + 1;
for (int i = 0; i < count; i++) {
this.add(new JLabel(text));
}
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int w = e.getComponent().getWidth();
int h = e.getComponent().getHeight();
sizeLabel.setText("Size: " + w + "\u00d7" + h);
}
});
}
}
Swing components (except JLabel) are opaque by default. This means:
you don't need playerPanel.setOpaque(true)
most components you add to the panel will be opaque and cover the background of your playerPanel.
Also, the BoxLayout respects the maximum size of any component you add to the panel. So if you add a component:
like a JButton which has a defined maximum size, you will see the button on top of the playerPanel and the background will surround the button.
like a JPanel, which does not have a defined maximum size, the panel will be resized to fill the entire area of the playerPanel and you won't see the background of the playerPanel.
If you want to see the background of the playerPanel show through a component added to the playerPanel, then you need to use setOpaque(false) on the component. For example:
JPanel child = new JPanel();
child.setOpaque( false );
playerPanel.add( child );
I'm trying to create an application in 3 parts : 3 labels and 3 gridlayouts. When we click on a label, the corresponding gridlayout disappear and the frame replace automatically the components at the right place. I created a simple snippet :
import java.awt.Button;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestLayout extends JFrame{
private JPanel content;
private JLabel[] lbl;
private JPanel[] pnl;
private Boolean[] ih;
public TestLayout(){
setTitle("Test");
setSize(new Dimension(300, 400));
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
lbl = new JLabel[3];
pnl = new JPanel[3];
ih = new Boolean[3];
content = new JPanel(new GridLayout(6, 1));
for(int i=0; i<3; i++){
lbl[i] = new JLabel("Label" + i);
lbl[i].addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
for(int i=0; i<3; i++){
if(e.getSource() == lbl[i]){
//pnl[i].setVisible(!pnl[i].isVisible());
if(ih[i]) content.remove(pnl[i]);
else content.add(pnl[i]);
ih[i] = !ih[i];
}
}
}
});
pnl[i] = new JPanel(new GridLayout(3, 3));
}
for(int i=0; i<9; i++){
pnl[0].add(new Button("" + (i+1)));
pnl[1].add(new Button("" + (i+10)));
pnl[2].add(new Button("" + (i+19)));
}
for(int i=0; i<3; i++){
content.add(lbl[i]);
content.add(pnl[i]);
ih[i] = true;
}
add(content);
setVisible(true);
}
public static void main(String[] args){
new TestLayout();
}
}
The first problem is the use of a global gridlayout which resize all the components at the same size, but I think it would be better if labels could be smaller than the grilayouts.
The second problem is that even if the gridlayout is removed or setVisible(false), it still take a blank place in the global container.
What I get :
What I was expecting :
The only thing I don't wanna use is a GridBagLayout.
I was thinking about create a method init() which one remove all components of the global container then re add all the labels and all the panels, then create another method which do the exact same as the init() method but take a number as parameter (for example 2) then re add all the components excepting the second gridlayout. But I think it's a dirty way to do that because the container will content an empty case at the end and I think there is a better way than removing and re adding all the components (which basically doesn't solve the first problem of label's size)
How can I avoid theses problems ?
Try using a vertical BoxLayout.
Read the section from the Swing tutorial on How to Use BoxLayout for more information and working examples.
On the net I read that to add a component to a JscrollPane we must perform:
scrollPane.getViewport().setView(jpanel);
Well, this is my code. To show multiple components, in this case JButtons, I am trying to add them into multiple JPanels and add these last in order at the end. But only the last JPanel is shown. Why?
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import layout.TableLayout;
public class Main {
public static void main(String argv[]) {
JFrame jframe = new JFrame("Protocollo UTL");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(1200, 450);
JPanel body = new JPanel();
double[][] size = {
{0.05},
{0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05}
};
body.setLayout(new TableLayout(size));
for(int i=0; i<19; i++) {
body.add(new JButton(String.valueOf(i)), "0,"+String.valueOf(i));
}
JPanel body2 = new JPanel();
body2.setLayout(new TableLayout(size));
for(int j=0; j<6; j++) {
body2.add(new JButton(String.valueOf(j)), "0,"+String.valueOf(j));
}
JScrollPane scrollPane = new JScrollPane(body,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.getViewport().setView(body);
scrollPane.getViewport().setView(body2);
jframe.add(scrollPane);
jframe.setVisible(true);
}
}
You are overriding the first one with the second statement
scrollPane.getViewport().setView(body);
scrollPane.getViewport().setView(body2);
You should add both JPanels to some parent component, and set that component as view. Something like this:
Container cont = new Container();
cont.add(body);
cont.add(body2);
scrollPane.getViewport().setView(cont);
EDIT
I don't think you need that line (setView(...)) at all. Try this (put this instead of last four lines)
Container cont = new Container();
cont.add(scrollPane);
cont.add(body2);
cont.setLayout(new GridLayout());
jframe.add(cont);
jframe.setVisible(true);
I have a GUI program which includes JLabels and JButtons and basically I want a layout that would help me display them as follows:
Label1 Button1
Label2 Button2
Label3 Button3
.....
Is there a layout that would allow me to achieve the above result?
I have looked at this example but is too complex and was wondering if there is anything automated that I can use?
This is one of the few things for which I'd recommend (a utility method and) GroupLayout as seen in this answer.
You can use GridLayout. Documentation here.
This is just for simplicity, and for your question. GUI is really dependent on what you would like to do and is really a thing that can be hardly automated..., and i don't think you only want those 6 elements on your GUI, but theoretically this will do it:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUITest {
private Box labelbox = new Box(BoxLayout.Y_AXIS);
//Y_AXIS means they are placed vertically in the box
private Box buttonbox = new Box(BoxLayout.Y_AXIS);
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
public void makeGUI1() {
for (int i = 1; i <= 3; i++) {
//if you want to save the references, you should make
//an ArrayList<JLabel> and add each of them to it
JLabel label = new JLabel("Label " + i);
labelbox.add(Box.createVerticalStrut(5));
//these are for giving the labels some extra space
//between them vertically to be in line with the buttons
labelbox.add(label);
labelbox.add(Box.createVerticalStrut(10)); //these are too
}
for (int i = 1; i <= 3; i++) {
//if you want to save the references, you should make
//an ArrayList<JButton> and add each of them to it
JButton button = new JButton("Button " + i);
buttonbox.add(button);
}
panel.add(labelbox, BorderLayout.EAST);
//you can find picture of each constant:
//http://download.java.net/jdk7/archive/b123/docs/api/java/awt/BorderLayout.html
panel.add(buttonbox, BorderLayout.WEST);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GUITest guitest = new GUITest();
guitest.makeGUI1();
}
});
}
}
You can also use obj.setBounds(LeftSpaceParameter,TopSpaceParameter) with which you can place the gui elements or objects at any position of your choice. You need to put the default layout to null
yet gridLayout is much easier. .
I've seen a few examples of this, and I've tried with the following code. I'm trying to change the content pane when portraitB is selected and then run the other class file.
//imported java libraries
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.UIManager;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.Dimension;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class birthdayCardGUI implements ActionListener
{
//Welcome Screen
JPanel welcomeP, welcomeImageP, portraitP, landscapeP, backP;
JLabel welcomeImageL;
JButton portraitB, landscapeB, backB;
//Portrait Screen
JTabbedPane tabbedPane;
JPanel portraitOne;
JLabel test;
public JFrame frame;
//Colours
int colourOne = Integer.parseInt( "c1c7f9", 16);
Color Blue = new Color( colourOne );
public birthdayCardGUI() throws Exception
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
JFrame frame = new JFrame("birthday Card Maker!");
frame.setExtendedState(frame.NORMAL);
frame.getContentPane().add(create_Content_Pane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 700); //Size of main window
frame.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
//sets frame location
int fw = frame.getSize().width;
int fh = frame.getSize().height;
int fx = (dim.width-fw)/2;
int fy = (dim.height-fh)/2;
//moves the frame
frame.setLocation(fx, fy);
}
public JPanel create_Content_Pane() throws Exception
{
JPanel TotalGUI = new JPanel();
//TotalGUI.setBackground(Blue);
TotalGUI.setLayout(null);
//Welcome Panel
welcomeP = new JPanel();
Border etched = BorderFactory.createBevelBorder(10);
Border titled = BorderFactory.createTitledBorder(etched, "Welcome");
welcomeP.setBorder(titled);
welcomeP.setLayout(null);
welcomeP.setLocation(0,0);
welcomeP.setSize(485, 680);
welcomeP.setBackground(Blue);
TotalGUI.add(welcomeP);
welcomeImageP = new JPanel();
welcomeImageP.setLayout(null);
welcomeImageP.setLocation(88,20);
welcomeImageP.setSize(324, 225);
welcomeP.add(welcomeImageP);
String welcomeG = "Welcome Image.png";
ImageIcon WelcomeG = new ImageIcon(welcomeG);
welcomeImageL = new JLabel( WelcomeG, JLabel.CENTER);
welcomeImageL.setSize(324, 225);
welcomeImageL.setLocation(0,0);
welcomeImageP.add(welcomeImageL);
portraitB = new JButton("Portrait");
portraitB.setSize(100, 30);
portraitB.setLocation(200, 295);
portraitB.addActionListener(this);
welcomeP.add(portraitB);
landscapeB = new JButton("Landscape");
landscapeB.setSize(100, 30);
landscapeB.setLocation(200, 335);
landscapeB.addActionListener(this);
welcomeP.add(landscapeB);
TotalGUI.setOpaque(true);
return TotalGUI;
}
public void create_Portrait_Pane()
{
PortraitGUI portrait = new PortraitGUI();
getContentPane().removeAll();
getContentPane().add(portrait.PortraitGUI);
getContentPane().doLayout();
update(getGraphics());
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == portraitB)
{
create_Portrait_Pane();
}
}
//MAIN METHOD
public static void main(String[] args) throws Exception
{
birthdayCardGUI CGUI = new birthdayCardGUI();
}
}
And this is the PortraitGUI file that creates the new content pane.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class PortraitGUI extends JPanel implements ActionListener
{
JPanel frontPageP;
JLabel frontPageL;
//Color White;
int intValue = Integer.parseInt( "FFFFFF", 16);
Color White = new Color(intValue);
public JPanel PortraitGUI() throws Exception
{
JPanel PortraitGUI = new JPanel();
PortraitGUI.setLayout(null);
frontPageP = new JPanel();
frontPageP.setBackground(White);
frontPageP.setSize(350, 400);
frontPageP.setLocation(20, 70);
PortraitGUI.add(frontPageP);
frontPageL = new JLabel("Front Page");
frontPageL.setLocation(10, 5);
frontPageL.setSize(70, 30);
frontPageL.setHorizontalAlignment(JTextField.CENTER);
PortraitGUI.add(frontPageL);
PortraitGUI.setOpaque(true);
return PortraitGUI;
}
public void actionPerformed(ActionEvent e)
{
}
}
There are several problems in your code, but one of your main problems comes from your shadowing of the JFrame class field in your constructor leaving the class field null and non-usable. To fix this, don't redeclare this variable. Thus change this:
JFrame frame = new JFrame("birthday Card Maker!");
to this:
// this uses the JFrame variable declared in the class.
frame = new JFrame("birthday Card Maker!");
Then you can use this variable later on in a method where you swap contents of the contentPane:
public void create_Portrait_Pane() throws Exception {
PortraitGUI portrait = new PortraitGUI();
frame.getContentPane().removeAll(); // now you can use the frame variable
frame.getContentPane().add(portrait);
//!! getContentPane().doLayout();
//!! update(getGraphics()); // WTF?
((JPanel)frame.getContentPane()).revalidate();
frame.repaint();
}
Having said this, myself, I'd probably use a JPanel that uses CardLayout as my Container for swapping views (other JPanels).
Also, you appear to have a "pseudo" constructor here:
public JPanel PortraitGUI() throws Exception {
Why not just use a real constructor?:
public PortraitGUI() throws Exception {
setLayout(null);
frontPageP = new JPanel();
frontPageP.setBackground(White);
frontPageP.setSize(350, 400);
frontPageP.setLocation(20, 70);
add(frontPageP);
frontPageL = new JLabel("Front Page");
frontPageL.setLocation(10, 5);
frontPageL.setSize(70, 30);
frontPageL.setHorizontalAlignment(JTextField.CENTER);
add(frontPageL);
setOpaque(true);
}
Also for good programming practice you'll want to avoid using a plain-vanilla Exception class and instead throw or catch specific exceptions.
Next, you're going to want to get out of the habit of using absolute size and position and instead using the layout managers for doing what they do best.
Edit:
replies to your recent comments
The reason I used public "JPanel" PortraitGUI is because it was throwing the error or return type required,
This was fixing the wrong thing though as the better solution was to make it a true constructor, not to give it a return type.
and I coded the class the same as create_Content_Pane(); with returning a Panel. Also the return type required error came up a few times.
Again, it's important to know why the error is occurring rather than fixing the wrong thing.
The update(getGraphics()); was also a method I tried from code examples I found with the same problem.
Surely that didn't come from a Swing example but more likely an older AWT example. You don't do that sort of coding with Swing.