So I was coding a Punnett square applet to automize a few simple biology calculations and output a simple Punnett square visual. For those of you who don't know, a Punnett square is just a device used in Biology to find ratios of a certain genotype in all the possible children. It's relatively simple;and example would be parents Aa and aa would create offspring of Aa, Aa, aa, and aa ( just crossed them). I have implemented this for single and double genes (Aa+Aa; AaBb+AaBb), with single genes being in a 2x2 table and double being in a 4x4 table.
The issue I am having is with my display- What I want is for each item in the 4x4 table to be centered ( they are currently all located to the left of each cell). Additionally, I wanted to find a way to put the parent's genes on the side of the table (so to the left and to the top to indicate each parent).
I am somewhat a novice at GUI, and was struggling to find any help online in regards to this kind of situation, so was wondering whether you could help.
Here is the code for the GUI class:
//Imports
public class GeneticsGUI
{
public static void main(String[] args)
{
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.setSize(600, 600);
JTextField parent1 = new JTextField();
JTextField parent2 = new JTextField();
JPanel top = new JPanel(new GridLayout(3,2));
top.add(new JLabel("Parent 1:"));
top.add(parent1);
top.add(new JLabel("Parent 2:"));
top.add(parent2);
JButton submit = new JButton("Calculate");
submit.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==submit)
{
String p1 = parent1.getText();
String p2 = parent2.getText();
if(p1!=null&&p2!=null&&p1.length()==2&&p2.length()==2)
{
JPanel c2 = new JPanel();
JFrame window = new JFrame("Genetics");
window.add(c2);
window.setContentPane(c2);
window.setSize(600, 400);
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setVisible(true);
String[][] mono = Genetics.monohybridPunett(p1, p2);
for(int row = 0; row<2 ; row++)
{
for(int col = 0; col<2; col++)
{
mono[row][col] = " "+ mono[row][col];
}
}
JTable table = new JTable(mono.length,mono.length);
table.setShowGrid(true);
for(int i = 0; i<mono.length; i++)
for(int j = 0; j<mono.length; j++)
table.setValueAt(mono[i][j], i, j);
DefaultTableCellRenderer t = new DefaultTableCellRenderer();
t.setHorizontalTextPosition(DefaultTableCellRenderer.CENTER);
t.setVerticalTextPosition(DefaultTableCellRenderer.CENTER);
table.setSize(300, 300);
table.isCellEditable(0,0);
table.setRowHeight(100);
c2.add(table,BorderLayout.EAST);;
c2.revalidate();
}
else if(p1!=null&&p2!=null&&p1.length()==4&&p2.length()==4)
{
JPanel c2 = new JPanel();
JFrame window = new JFrame("Genetics");
window.add(c2);
window.setContentPane(c2);
window.setSize(600, 500);
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setVisible(true);
String[][] di = Genetics.dihybridPunett(p1, p2);
JTable table = new JTable(di.length,di.length);
table.setShowGrid(true);
DefaultTableModel model = new DefaultTableModel(di,new Object[]{"AaBb","AaBb","",""});
table.isCellEditable(0, 0);
table.setModel(model);
table.setRowHeight(100);
table.getColumnModel().getColumn(0).setPreferredWidth(100);
table.getColumnModel().getColumn(1).setPreferredWidth(100);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(100);
c2.add(table,BorderLayout.CENTER);
c2.revalidate();
}
}
}
});
top.add(submit);
content.add(top, BorderLayout.NORTH);
JFrame window = new JFrame("Genetics");
window.add(content);
window.setContentPane(content);
window.setSize(600,150);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
Related
My assignment is to create 2 JPanels, one for a 2d array, 6 rows of 5 empty JTextFields and another for JButtons that should somewhat resemble an on-screen keyboard. I created the JPanels with the empty JTextFields and JButtons, now I need a way so that when I press a JButton with a letter from the alphabet it will assign that letter to the first available JTextField on the first available row and move one column at a time until the whole row is filled with letters (trying to add letters to a full row should do nothing). I also need to create a backspace button which I have that will remove the last letter (pressing backspace on an empty row should do nothing).
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Wordle extends JFrame implements ActionListener
{
private JPanel p1;
private JPanel p2;
private JTextField [][] g;
public Wordle()
{
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p1 = new JPanel();
p1.setLayout(new GridLayout(6, 5));
g=new JTextField [5][6];
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c]= new JTextField();
getContentPane().add(g[r][c]);
p1.add(g[r][c]);
}
}
p2 = new JPanel();
p2.setLayout(new GridLayout(4, 7));
JButton a= new JButton("A");
a.addActionListener(this);
p2.add(a);
JButton b= new JButton("B");
b.addActionListener(this);
p2.add(b);
JButton c= new JButton("C");
c.addActionListener(this);
p2.add(c);
JButton d= new JButton("D");
d.addActionListener(this);
p2.add(d);
JButton e= new JButton("E");
e.addActionListener(this);
p2.add(e);
JButton f= new JButton("F");
f.addActionListener(this);
p2.add(f);
JButton g= new JButton("G");
g.addActionListener(this);
p2.add(g);
JButton h= new JButton("H");
h.addActionListener(this);
p2.add(h);
JButton i= new JButton("I");
i.addActionListener(this);
p2.add(i);
JButton j= new JButton("J");
j.addActionListener(this);
p2.add(j);
JButton k= new JButton("K");
k.addActionListener(this);
p2.add(k);
JButton l= new JButton("L");
l.addActionListener(this);
p2.add(l);
JButton m= new JButton("M");
m.addActionListener(this);
p2.add(m);
JButton n= new JButton("N");
n.addActionListener(this);
p2.add(n);
JButton o= new JButton("O");
o.addActionListener(this);
p2.add(o);
JButton p= new JButton("P");
p.addActionListener(this);
p2.add(p);
JButton q= new JButton("Q");
q.addActionListener(this);
p2.add(q);
JButton r= new JButton("R");
r.addActionListener(this);
p2.add(r);
JButton s= new JButton("S");
s.addActionListener(this);
p2.add(s);
JButton t= new JButton("T");
t.addActionListener(this);
p2.add(t);
JButton u= new JButton("U");
u.addActionListener(this);
p2.add(u);
JButton v= new JButton("V");
v.addActionListener(this);
p2.add(v);
JButton w= new JButton("W");
w.addActionListener(this);
p2.add(w);
JButton x= new JButton("X");
x.addActionListener(this);
p2.add(x);
JButton y= new JButton("Y");
y.addActionListener(this);
p2.add(y);
JButton z= new JButton("Z");
z.addActionListener(this);
p2.add(z);
JButton BackSpace= new JButton("<-");
BackSpace.addActionListener(this);
p2.add(BackSpace);
JButton Enter= new JButton("[");
Enter.addActionListener(this);
p2.add(Enter);
this.getContentPane().add(p1,BorderLayout.NORTH);
this.getContentPane().add(p2,BorderLayout.SOUTH);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) //need help with
{
if(e.getSource().equals("A"))
{
for(int r=0; r<g.length; r++)
{
for(int c=0; c<g[r].length; c++)
{
g[r][c].setText("A");
}
}
}
}
public static void main(String[] args)
{
new Wordle();
}
}
This is my code and my main issue is setting the text in the 2d array of JTextFields using actionlistener, I don't mind doing each if loop for each letter individually as long as it makes sense and works the way I intended it to, btw if you haven't already noticed this is the game "Wordle" I am trying to make, I'm still a newbie programmer and all of this is new to me so some kind of intuitive explanation would be much appreciated.
This line if(e.getSource().equals("A")) is your first issue. It simply will not work because e.getSource() returns an object that will never equal "A".
Instead, you need to first cast the source to the correct object type like so:
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
Now we can now get the text from the button using use getText() like this (Although there is a smarter solution we can use down below):
public void actionPerformed(ActionEvent e) //need help with
{
JButton clicked = (JButton)e.getSource();
if(clicked.getText().equals("A")) {
...
The next issue you face is how you store the data, you need to track the current cell using a class variable, rather than just filling up the whole array:
private int row = 0;
private int column = 0;
Then all together the changes might look a bit like this:
//Class variables
private int row = 0;
private int column = 0;
public void actionPerformed(ActionEvent e) //need help with
{
//Cast the event source to a button
JButton clicked = (JButton)e.getSource();
//Handle backspace
if(clicked.getText().equals("<-"))
{
//Decrease the tracking number
column--;
//Make sure that only valid cells are back spaced
if(column < 0)
{
column = 0;
}
//Set the cell to be blank
g[row][column].setText("");
}
//Handle enter
else if(clicked.getText().equals("["))
{
//Add your behaviour here
....
//Finally move to the next row
row++;
}
//Handle the rest of the letter buttons here
else
{
//We don't need `for` loops, we can just directly add the letter from
//the clicked button to the correct place in the array like so
g[row][column].setText(clicked.getText);
//Increment the tracking numbers
column++;
//Move to the next row when the column value is over 5:
if(column > 4)
{
//Move to the next row
row++;
//Reset the column number to 0
column = 0;
}
}
}
I am having some trouble figuring out how to do this. I have created a tile class to associate with my tile objects, but I'm unsure of how to add my ArrayList of tile objects to my JPanel.
Here is what I have so far:
public class First implements Runnable{
public void run() {
// TODO Auto-generated method stub
JFrame fr = new JFrame("Frame");
fr.setVisible(true);
fr.setSize(300,700);
JPanel p = new JPanel(new GridLayout(0,1));
p.setVisible(true);
fr.add(p);
JLabel blue = new JLabel("a");
//blue.setOpaque(true);
//blue.setBackground( Color.BLUE );
p.add(blue);
JLabel red = new JLabel("b");
//red.setOpaque(true);
//red.setBackground( Color.RED);
p.add(red);
JLabel green = new JLabel("c");
//green.setOpaque(true);
//green.setBackground( Color.GREEN);
p.add(green);
JLabel orange = new JLabel("d");
orange.setOpaque(true);
orange.setBackground( Color.ORANGE);
p.add(orange);
char a = 0;
char b = 0;
char c = 0;
char d = 0;
Tile ta = new Tile(a);
Tile tb = new Tile(b);
Tile tc = new Tile(c);
Tile td = new Tile(d);
//p.(ta);
ArrayList<Tile>tile = new ArrayList<Tile>();
tile.add(ta);
tile.add(tb);
tile.add(tc);
tile.add(td);
for(Tile s: tile){
System.out.println("Printed:"+s);
}
}
}
I'm not clear if this is what you are asking. But if you want to display the contents of an ArrayList on a JPanel, you can just iterate through it.
for (Tile t:tile) p.add(t);
This assumes that Tile is an extension of Component.
Ok, I'm kinda new to java. I'm making a program that solves for one step equations. I'm having some difficulties running it though. Here is the code for my main file, Main.java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
Solve solve = new Solve();
JButton add = new JButton("Add");
JButton sub = new JButton("Subtract");
JButton mult = new JButton("Multiply");
JButton div = new JButton("Divide");
JButton solv = new JButton("Solve!");
JTextArea one = new JTextArea();
JLabel two = new JLabel(" = ");
JLabel three = new JLabel("X");
JLabel four = new JLabel();
JTextArea five = new JTextArea();
JLabel solved = new JLabel();
JPanel row1 = new JPanel();
JPanel row2 = new JPanel();
JPanel row3 = new JPanel();
public double funct;
public Main() {
super("Solving a one step equation!");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
GridLayout layout = new GridLayout();
setLayout(layout);
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER);
row1.setLayout(layout1);
row1.add(add);
row1.add(sub);
row1.add(mult);
row1.add(div);
row1.add(solv);
add(row1);
add.addActionListener(this);
sub.addActionListener(this);
mult.addActionListener(this);
div.addActionListener(this);
solv.addActionListener(this);
GridLayout layout2 = new GridLayout(1, 1, 1, 1);
row2.setLayout(layout2);
row2.add(one, BorderLayout.CENTER);
row2.add(two, BorderLayout.CENTER);
row2.add(three, BorderLayout.CENTER);
row2.add(four, BorderLayout.CENTER);
row2.add(five);
add(row2, BorderLayout.CENTER);
GridLayout layout3 = new GridLayout(5, 5, 5, 5);
row3.setLayout(layout3);
row3.add(solved);
add(row3);
}
public static void main(String[] args) {
Main frame = new Main();
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if(source == add)
{
four.setText(" + ");
funct = 1;
}
else if(source == sub)
{
four.setText(" - ");
funct = 2;
}
else if(source == mult)
{
four.setText(" * ");
funct = 3;
}
else if(source == div)
{
four.setText(" / ");
funct = 4;
}
if(source == solv)
{
if(funct == 1)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Add(Ones, Twos));
}
else if(funct == 2)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Sub(Ones, Twos));
}
else if(funct == 3)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Mult(Ones, Twos));
}
else if(funct == 4)
{
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
solved.setText("X = " + solve.Div(Ones, Twos));
}
}
}
}
Here is the code for my other file, Solve.java
public class Solve {
public double Add(double One, double Two)
{
return One - Two;
}
public double Sub(double One, double Two)
{
return One + Two;
}
public double Mult(double One, double Two)
{
return One / Two;
}
public double Div(double One, double Two)
{
return One * Two;
}
}
Some help would be appreciated. Anyone see what I'm doing wrong?
You get a NumberFormatException once 'Solve' button is clicked. It seems like a copy/paste issue - you are not retrieving the correct numbers. You are trying to convert 'X' string to double. It is best if you give meaningful names to your variables. To fix the exception, try this, replace :
double Ones = Double.parseDouble(three.getText());
double Twos = Double.parseDouble(three.getText());
with:
double Ones = Double.parseDouble(one.getText());
double Twos = Double.parseDouble(five.getText());
Get familiar with Java Code Conventions, Naming Conventions section in particular.
In addition to #Max's helpful answer, here are a few other suggestions:
Setting the frame's layout to new GridLayout() defaults to a single row and column with no padding. As an alternative, consider new GridLayout(0, 1, 5, 5), which produces any number of rows in one column with 5x5 padding. Then you can focus on the layout of each row:
row1.setLayout(new FlowLayout(FlowLayout.CENTER));
row2.setLayout(new FlowLayout(FlowLayout.CENTER));
row3.setLayout(new GridLayout(1, 1, 5, 5));
Move your setVisible() call to the end of the frame's constructor:
pack();
setLocationRelativeTo(null);
setVisible(true);
Consider getRootPane().setDefaultButton(solv) to make the Solve button the default.
Consider making addition the default:
private JLabel four = new JLabel("+");
private int funct = 1; // add by default
Consider using JTextField for number entry:
private JTextField one = new JTextField(10);
private JTextField five = new JTextField(10);
I'm trying to place a JList inside of a JScrollPane and have it alphabetically list the entries in vertical columns like this:
A D G
B E H
C F
However when the JList runs out of space to display more entries, I'd like the JScrollPane to scroll only in the vertical direction.
This works when I use VERTICAL_WRAP. However, it seems like when I use vertical wrap I get a horizontal scrollbar and when I use HORIZONTAL_WRAP I get the scrollbar I want, but the items get placed in an order that I don't like. Can I have my cake and eat it too? Here's a simple example of what I'm trying to do.
This is the closest I could get, but I'd like to be able to scroll vertically while maintaining the vertical alphabetical ordering.
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(0);
final JScrollPane scrollPane = new JScrollPane(list);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(800, 400));
frame.pack();
frame.setVisible(true);
}
}
One solution I've though of is:
If the cell size is known I can create a component listener, and listen for a resize event. When that event is triggered I can calculate the desired row count in order to prevent horizontal scrolling. This just seems like a hack, and I'm not sure how it could work with variable sized text components.
I think your solution is just fine, and not a hack at all. Any built-in feature would have to do basically the same thing anyways.
Here's a modification to your example that does what you want.
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
final JScrollPane scrollPane = new JScrollPane(list);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(800, 400));
frame.pack();
list.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
fixRowCountForVisibleColumns(list);
}
});
fixRowCountForVisibleColumns(list);
frame.setVisible(true);
}
private static void fixRowCountForVisibleColumns(JList list) {
int nCols = computeVisibleColumnCount(list);
int nItems = list.getModel().getSize();
// Compute the number of rows that will result in the desired number of
// columns
int nRows = nItems / nCols;
if (nItems % nCols > 0) nRows++;
list.setVisibleRowCount(nRows);
}
private static int computeVisibleColumnCount(JList list) {
// It's assumed here that all cells have the same width. This method
// could be modified if this assumption is false. If there was cell
// padding, it would have to be accounted for here as well.
int cellWidth = list.getCellBounds(0, 0).width;
int width = list.getVisibleRect().width;
return width / cellWidth;
}
}
Is this what you're going for? (Might need to change the preferred size...)
public class ScrollListExample {
static List<String> stringList = new ArrayList<String>();
static {
for (int i = 0; i < 500; i++) {
stringList.add("test" + i);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame();
final Container contentPane = frame.getContentPane();
final JList list = new JList(stringList.toArray());
final JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scrollPane);
frame.setPreferredSize(new Dimension(200,200));
frame.pack();
frame.setVisible(true);
}
}
Brilliant Code #Kevin K... I suggest a small modification to avoid ArithmeticException (Divide by zero)
private int computeVisibleColumnCount(JList list)
{
int cellWidth = list.getCellBounds(0, 0).width;
int width = list.getVisibleRect().width;
return width == 0 ? 1 : width / cellWidth;
}
I'm making a Sudoku program in java to learn some algorithms so I want the user to be able to input an unsolved Sudoku puzzle. Here is what I have so far that creates 81 (9x9) boxes:
JTextField input[] = new JTextField[80];
for(int i = 0; i <= 79; i++)
{
input[i] = new JTextField();
input[i].setPreferredSize(new Dimension(30,30));
f.getContentPane().add(input[i]);
}
When I run this program though all I get is just one input field. I know that all the text fields and initialized, created and added to the jframe. I know you have to mess this the layout but I'm not sure how to do that. Any help is appropriated.
Use a JPanel with GridLayout.
Also:
JTextField input[] = new JTextField[80];
That's 80 (not 81) text fields.
Update: (sample code)
public class SodokuBoardDemo {
public static void main(String... args) {
SudokuBoard board = new SudokuBoard();
JFrame frame = new JFrame("Sodoku");
frame.add(board);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static class SudokuBoard extends JPanel {
public SudokuBoard() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
setLayout(new GridLayout(3, 3));
BoardPart input[] = new BoardPart[9];
for (int i = 0; i < 9; i++) {
input[i] = new BoardPart();
add(input[i]);
}
}
public static class BoardPart extends JPanel {
public BoardPart() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));
setLayout(new GridLayout(3, 3));
JTextField input[] = new JTextField[9];
for (int i = 0; i < 9; i++) {
input[i] = new JTextField();
input[i].setPreferredSize(new Dimension(30, 30));
add(input[i]);
}
}
}
}
}
If you are unsure about how to use different Layouts there is a great tutorial on Oracle documents. If you want to brush up on the components themselves you could also check out the tutorial on them. :)
ps: It might be me being too sleepy but it would appear that you have created 80 text fields not 81.