On screen Keyboard JButton fit text size exactly - java

I wrote this on screen keyboard that should display a keyboard.
my problem is that i want the JButtons fit their size of the labels and not to set fix size for all of the JButtons.
for example the numbers on keyboard: "1,2,3...." should get small jbutton and the keys "backspace" "tab" etc... should be bigger (fit the size of their label)
this is the code I wrote:
package Q2;
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JPanel{
private JButton[][] button;
private JPanel[] panel; //Array of panels for each buttons line
private JPanel parent;
private static final String[][] key = {
{"`","1","2","3","4","5","6","7","8","9","0","-","+","Backspace"},
{"Tab","Q","W","E","R","T","Y","U","I","O","P","[","]"},
{"Caps","A","S","D","F","G","H","J","K","L",";","'","\\","Enter"},
{"Shif","Z","X","C","V","B","N","M",",",".","?","/"},
{" ",",","<","v",">"}
};
//Constructor for main Panel
public MainPanel(){
super();
setLayout(new BorderLayout());
TextField textField= new TextField(20);
Font font1 = new Font("david", Font.BOLD, 22);
textField.setFont(font1);
add(textField,BorderLayout.CENTER);
//initialize the parent panel and array of 5 panels and the buttons array
parent = new JPanel();
parent.setLayout(new GridLayout(0,1));
panel = new JPanel[5];
button = new JButton[20][20];
for (int row = 0; row<key.length; row++){
panel[row] = new JPanel();
for (int column = 0; column<key[row].length; column++){
button[row][column] = new JButton(key[row][column]);
button[row][column].setPreferredSize(new Dimension(key[row][column].length()+80,30));
button[row][column].putClientProperty("row", row);
button[row][column].putClientProperty("column", column);
button[row][column].putClientProperty("key", key[row][column]);
//button[row][column].addActionListener(new MyActionListener());
panel[row].add(button[row][column]);
}
parent.add(panel[row]);
}
add(parent,BorderLayout.SOUTH);
}
/*
//panel for line 1 of keyboard buttons - numbers
protected JComponent getPanelLine1(){
JPanel panel1 = new JPanel();
for (int i=0; i<10; i++){
}
}
//panel for line 1 of keyboard buttons - Q-P
protected JComponent getPanelLine2(){
}
//panel for line 1 of keyboard buttons - A-L
protected JComponent getPanelLine3(){
}![enter image description here][1]
//panel for line 1 of keyboard buttons - Z-M
protected JComponent getPanelLine4(){
}
//panel for line 1 of keyboard buttons - space and arrows
protected JComponent getPanelLine5(){
}*/
}
image:

As discussed here, don't set the preferred size!
// button[row][column].setPreferredSize(new Dimension(key[row][column].length()+80,30));
Instead set the margins
button[row][column].setMargin(new Insets(10, 20, 10, 20));
// Insets ( top, left, bottom, right )
And/or set the font size
Font font = button[row][column].getFont();
String family = font.getFamily();
int style = font.getStyle();
button[row][column].setFont(new Font(family, style, 24));
You probably don't want to create a new font every iteration, but it's just showing you how to get the defaults from the button
Doing either of these things will increase the preferred size of the panel accordingly, taking into account the size of the text contained within it

Related

Sudoku Gui Issues

I am required to create a Suduku Game Board that looks like this:
Here are the requirements I need for this assignment, but am having some issues.
Use two for loops to draw the text fields instead of brute-force of listing 81 text fields. You should do something like:
for (int k = 1; k <= 9; k++)
{
JPanel level2 = new JPanel();
….
for (int i = 1; i <= 9; i++)
{
JTextField text = new JTextField();
…
}
gridPanel.add(level2);
}
I need 2 classes in
an application class named TestSudoku and a work class named SudokuLayout.
Implement the following visual gadgets and write listeners for them. These gadgets have the following behaviors:
Button “Reset”---when the button is clicked, the program will clear the text area, then output the string “Reset button clicked!” to the text area.
Button “Hint”---when the button is clicked, the program will clear the text area, then output the string “Hint button clicked!” to the text area.
Combobox “Difficulty”---when an item is selected, the program will clear the text area, then output the selected item name to the text area.
implement the listeners using loosely coupled methods (private listener class or private adapter class).
This is what I currently have..
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
public class SudokuLayout extends JFrame {
public SudokuLayout() {
JPanel board = new JPanel(new GridLayout(9, 9));
add(board);
JPanel[][] squares = new JPanel[9][9];
Border border = BorderFactory.createLineBorder(Color.BLACK);
for (int row = 1; row < 9; row++) {
for (int col = 1; col < 9; col++) {
squares[row][col] = new JPanel();
board.add(squares[row][col]);
}
}
JPanel menu = new JPanel();
menu.add(new JButton("Reset"));
menu.add(new JButton("Hint"));
menu.add(new JButton("Solve"));
menu.add(new JButton("New Puzzle"));
add(menu);
}
public static void main(String[] args) {
/** Create a frame and set its properties*/
JFrame frame = new SudokuLayout();
frame.setTitle("Sudoku");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null); //Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
The problem is that, with my current version, the right menu shows horizontally and I cannot see the grid. Moreover, I don't know how to add the output area.
When facing this kind of frames with Swing you need to divide the frame in sections and treat them separately. I mean, by looking at the image you can easily identify the Sudoku, the menu, and the output. Thus, your answer should try to first create each of them separately and then join them.
Considering this, you must notice:
There are 3 main components: sudoku, menu, and output
The 3 main components may use a BorderLayout since they are probably at WEST, EAST and SOUTH
The sudoku component is a 3x3 grid of 3x3 smaller grids (so you can change the black-border).
The menu component is a 5x1 grid with buttons in each position
The output component is a single text frame
So, you may need to change something to get the exact behaviour (button sizes and margins, options on the difficulty ComboBox) but your solution should look like this:
public class SudokuLayout extends JFrame {
public SudokuLayout() {
// Create panel for Sudoku
JPanel board = new JPanel();
board.setLayout(new GridLayout(3, 3));
board.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col) {
JPanel box = new JPanel(new GridLayout(3, 3));
box.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (int cell = 0; cell < 9; ++cell) {
box.add(new JTextField(2));
}
board.add(box);
}
}
// Create difficulty combo box
JComboBox<String> difficultyChoices = new JComboBox<>(new String[] { "Hard", "Easy" });
difficultyChoices.setSelectedIndex(0);
// Create menu panel
JPanel menu = new JPanel();
menu.setLayout(new GridBagLayout());
GridBagConstraints menuConstraints = new GridBagConstraints();
menuConstraints.anchor = GridBagConstraints.WEST;
menuConstraints.weightx = 0.5;
menuConstraints.weighty = 0.5;
menuConstraints.gridwidth = 2;
menuConstraints.gridx = 2;
menuConstraints.gridy = 0;
menu.add(new JButton("Reset"), menuConstraints);
menuConstraints.gridx = 2;
menuConstraints.gridy = 1;
menu.add(new JButton("Hint"), menuConstraints);
menuConstraints.gridx = 2;
menuConstraints.gridy = 2;
menu.add(new JButton("Solve"), menuConstraints);
menuConstraints.gridx = 2;
menuConstraints.gridy = 3;
menu.add(new JButton("New Puzzle"), menuConstraints);
menuConstraints.weighty = 1.0;
menuConstraints.gridx = 2;
menuConstraints.gridy = 4;
menu.add(new JLabel("Difficulty:"), menuConstraints);
menuConstraints.fill = GridBagConstraints.HORIZONTAL;
menuConstraints.weightx = 0.5;
menuConstraints.weighty = 0.5;
menuConstraints.gridwidth = 2;
menuConstraints.gridx = 0;
menuConstraints.gridy = 5;
menu.add(difficultyChoices, menuConstraints);
// Create output panel
JTextArea output = new JTextArea(5, 20);
output.setEditable(false);
output.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE), "Output Area"));
// Join the 3 panels on the frame
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(board, BorderLayout.WEST);
cp.add(menu, BorderLayout.EAST);
cp.add(output, BorderLayout.SOUTH);
}
public static void main(String[] args) {
// Create a frame and set its properties
JFrame frame = new SudokuLayout();
frame.setTitle("TestSudoku");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null); // Center the frame
// Setup the window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
UPDATE: I update my answer with a GridBagLayout for the menu and a TextArea with border for the output.

How to make a JPanel into a BufferedImage Java

I have a half-working paint/turtle graphics program but I am having a few issues.
I am going to need to save the image that is drawn at some point - I know I need to use a BufferedImage but how do I go about this? I have attached a little bit of my code below.
In short I have a JFrame with a text field and a white JPanel below it. When commands are typed in by the user lines are drawing through another class and appear on the JPanel. I know I won't be able to save them off the JPanel to an image but have no understanding of how to implement a buffered image and what i would/wouldn't need to change.
Please be kind, I am new to programming and haven't finished some parts of my code yet.
Thanks in advance
public class Turtle2 extends JFrame implements ActionListener, KeyListener{
JMenuBar menuBar;
JMenu help, file;
JPanel panel, panel2;
JMenuItem newO, load, save, exitO, about;
JTextField text;
int savecounter = 0, newcounter = 1, part2I = 0;
int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
int trigger = 1, turnleftconstant = 0, turnrightconstant =0, direction =0;
int col = 0;
public Turtle2() {
setLayout(new FlowLayout());
setSize(1000, 1000);
setTitle("Graphic");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//menu bar
//sets up general look of window
panel = new JPanel();
panel.setBackground(Color.darkGray);
//implements box layout
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
//sets up drawing area
panel2 = new JPanel();
panel2.setPreferredSize(new Dimension(500, 500));;
panel2.setBackground(Color.WHITE);
panel2.setBorder(BorderFactory.createLineBorder(Color.darkGray, 3));
//starting point on drawing area co-ordinates
x1 = 15; x2 = 15; y1 = 230; y2 =230;
//starting point implemented
LinePen first = new LinePen(x1, y1, x2, y2, col);
panel2.add(first);
//sets up user input text box
text = new JTextField(30);
//add action listener to text box - ready for input and details responses
text.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//retrieves user input
String actions = text.getText();
first.setVisible(true);
//commands from text
//add the command line textfeild to the interface
panel.add(text);
//uses border layout to set the layout of the interface
getContentPane().add(BorderLayout.NORTH, panel);
getContentPane().add(BorderLayout.CENTER, panel2);
//set the size of the interface
setSize(600,600);
//ensure the interface is visible
setVisible(true);
}
I would keep an array of all your lines, then iterate through them, and then use img.createGraphics() to draw your lines and other graphics.

Improper sizing using GridBagLayout

I am trying to use a GridBagLayout to have a JFrame that contains a JPanel that has a grid layout and a JPanel with just a large button. I want the rows to all be the same size, and the JPanel with the JButton to be the same size as one row. However, the button panel, which is currently empty, is about 1/3 of the JFrame. I'm not quite sure what's happening, but it is pretty important to me that I maintain this structure because the rest of my code uses this. Any help is appreciated, and thank you in advance.
This is my code:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class Minesweeper extends JPanel {
private final int SIZE = 7;
public void startGame(){
JFrame holder = new JFrame();
JPanel window = new JPanel();
JPanel pan = new JPanel();
holder.setLayout(new GridBagLayout());
GridBagConstraints con = new GridBagConstraints();
con.weightx = 1;
con.weighty = 1;
con.gridx = 0;
con.gridy = 0;
con.fill = GridBagConstraints.BOTH;
con.gridheight = SIZE;
con.gridwidth = SIZE;
holder.getContentPane().setBackground(Color.darkGray);
holder.setSize(450, 450);
holder.setResizable(false);
holder.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBackground(Color.darkGray);
window.setLayout(new GridLayout(SIZE, SIZE));
for (int c=0; c<(SIZE*SIZE); c++){
int row = (c/SIZE);
int col = (c%SIZE);
JPanel p = new JPanel();
p.setBackground(Color.gray);
Border b = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
p.setBorder(b);
window.add(p);
}
holder.add(window, con);
con.gridx = 0;
con.gridy = SIZE+1;
con.gridheight = 0;
con.gridwidth = SIZE;
holder.add(pan, con);
holder.setVisible(true);
}
public static void main(String[] args){
Minesweeper start = new Minesweeper();
start.startGame();
}
}
This is what is being shown:
con.gridy = SIZE+1;
You can't specify a gridy value of 8. There are only two components added to the grid. The grid doesn't know that one of your panels happens to contain 7 rows of components. So the value should be 1.
This won't solve the problem but should clear up a misunderstanding of how GridBagLayout works.
holder.setSize(450, 450);
You are manually setting a size to the frame. Each component is originally sized at its preferred size. When there is extra space in the frame the space is distributed equally between the two components.
You should NOT be setting the size. Each component should determine its own size and then you should use pack(). So you need to use custom components that override the getPreferredSize() method to return the appropriate size for each component so pack() can do its job.
Also, the pack() is done just before the setVisible().

How to divide an applet/frame into two parts using panel and perform events between them [duplicate]

This question already has answers here:
Resizing issue with canvas within jscrollpane within jsplitpane
(3 answers)
Closed 8 years ago.
The program i want to make is
Divide an applet/frame(awt) into two parts using panel. The first panel contains four buttons naming ellipse, rectangle, circle and triangle. Taking one button and asking coordinates and make a figure on the other panel.
Please someone explain me the concept or working because im not good at layouts and know methods to use to convey from one panel to other..
Thank you very much
I would recommend starting out with a layout manager.. if you want 2 JPanels next to each other, you can use the GridLayout layout manager. It takes 2 arguments, and one of it's overloaded constructors takes 4 arguments.
setLayout(new GridLayout(rows, columns)); //one commonly used constructor
setLayout(new GridLayout(rows, columns, horizontalSpacePixels, verticleSpace));
GridLayout, when used will reshape to fit the largest component, and make each part of the grid an equal size-- however this isn't the case when you use a GridLayout inside of a GridLayout (the inner GridLayout might be too big to fit within the confines that the outer GridLayout puts on it.). If I simply do
JFrame jf = new JFrame("Laying the grid out");
jf.setLayout(new GridLayout(5, 5));
JPanel[] jp = new JPanel[25];
JLabel[] jl = new JLabel[25];
for(int i = 0; i < 25; i++) {
jp[i] = new JPanel();
jp[i].setBackground(Color.YELLOW);
jl[i] = new JLabel("This is label no. " + (i+1));
jp[i].add(jl[i]);
}
//now to add all 25 components in the 5x5 grid; you simply add them, and it
//automatically positions the jpanels in the order that you place them.. left to right.
for(int i = 0; i < 25; i++)
jf.add(jp[i]);
Here is an example program that involves a simple GridLayout, and an actionListener that responds to button events by changing one of the JPanel's color.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Gui {
private JPanel p2;
private JLabel side2;
private JFrame jf;
public static void main(String[] args){
new Gui();
}
public Gui(){
jf = new JFrame("Holds 2 panels side by side.");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(new GridLayout(1, 2));
JPanel p1 = new JPanel();
p2 = new JPanel();
p1.setBackground(Color.BLACK);
p2.setBackground(Color.BLACK);
p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
JLabel[] space = new JLabel[20];
for(int i = 0; i < 20; i++)
space[i] = new JLabel(" ");
JButton jb1 = new JButton("Button 1");
JButton jb2 = new JButton("Button 2");
jb1.addActionListener(new BListen());
jb2.addActionListener(new BListen());
p1.add(space[0]);
p1.add(jb1);
p1.add(space[1]);
p1.add(jb2);
p1.add(space[2]);
jf.add(p1);
side2 = new JLabel("Change the color here with the buttons there.");
side2.setForeground(Color.GREEN);
p2.add(side2);
jf.add(p2);
jf.setSize(600, 200);
jf.setVisible(true);
}
private class BListen implements ActionListener {
public void actionPerformed(ActionEvent e) {
String buttonClicked = e.getActionCommand();
if(buttonClicked.equals("Button 1")) {
JOptionPane.showMessageDialog(null, "You pressed Button 1.");
p2.setBackground(Color.BLUE);
side2.setForeground(Color.MAGENTA);
jf.setVisible(true);
}
else if(buttonClicked.equals("Button 2")) {
JOptionPane.showMessageDialog(null, "You pressed Button 2.");
p2.setBackground(Color.ORANGE);
side2.setForeground(Color.DARK_GRAY);
jf.setVisible(true);
}
}
}
}

Components in GridBagLayout are put to the center, without taking all free space

I have a GridBagLayout with two components: JRadioButton and JLabel. Text in a label differs by length. This GridbagLayout is added to JPanel. So when I have a lot of components they are not aligned well at the end. Here is what I mean:
-----radio btn-label-----
---radio btn-label --
-------radio btn-lbl-----
But I need the following:
-radio btn-label -
-radio btn-label -
-radio btn-lbl -
This is how my grid looks like for now:
public class MyPanel extends JPanel {
private JLabel info;
private JRadioButton select;
public MyPanel() {
this.achiev = achiev;
achievementInfo = new JLabel();
selectAchiev = new JRadioButton();
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.anchor = GridBagConstraints.LINE_START;
add(selectAchiev, constraints);
StringBuilder builder = new StringBuilder();
builder.append("<html><b>").append("some text").append("</b><p>");
builder.append("<i>").append("some more text").append("</i>");
info.setText(builder.toString());
constraints.gridx = 1;
constraints.gridy = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
add(info, constraints);
}
//--------------
JPanel panel = new JPanel(new BoxLayout(), BoxLayout.YAXIS);
for(int i = 0; i < 10; ++i) {
panel.add(new MyPanel());
}
You're adding 10 panels which all have their own gridbag layout, checkbox and label. So each panel has its own grid, and the width of the cells are computed independantly, based on the components they contain.
If you want a well-aligned single grid, you should have a single panel using GridBagLayout, and add your 10 labels and 10 checkboxes to this unique panel.
Moreover, you should give a weightx > 0 to the label's constraint if you really want it to fill horizontally.
I think you miss the weightx, weighty constraints as it is said in this GrigBadLayout document:
Unless you specify at least one non-zero value for weightx or weighty, all the components clump together in the center of their container. This is because when the weight is 0.0 (the default), the GridBagLayout puts any extra space between its grid of cells and the edges of the container.
If you want to make your components look like that, i refer using BoxLayout
private void init() {
Box outerBox = new Box(BoxLayout.Y_AXIS);
outerBox.add(createLineWithRadioButtonAndLabel());//line 1
outerBox.add(createLineWithRadioButtonAndLabel());//line 2
outerBox.add(createLineWithRadioButtonAndLabel());//line 3
add(outerBox);
}
private Box createLineWithRadioButtonAndLabel() {
Box line = new Box(BoxLayout.X_AXIS);
JRadioButton radio = new JRadioButton("radio button");
JLabel label = new JLabel("some text");
line.add(radio);
line.add(Box.createRigidArea(new Dimension(20, 1)));// add some horizontal space. Here is 20
line.add(label);
line.add(Box.createHorizontalGlue());
return line;
}

Categories