creating new jpanels using loop - java

i creating new jpanels using loop. but how i using different object name.
here is my code:
for(int i=0; i<panelnumbers.length(); i++){
MainConfig.page21.addNewPanel(MainConfig.page21.pos1, "INFORMACIÓN No. " + (i + 2));
}
public static void addNewPanel(int y, String title) {
Add a = new Add(title);
jLayeredPane3.add(a);
a.setBounds(0, y, 1333, 450);
jPanel1.setPreferredSize(new Dimension(1333, (pos + 480)));
jLayeredPane3.setPreferredSize(new java.awt.Dimension(1333, (pos + 480)));
jLayeredPane3.validate();
jScrollPane1.getViewport().setViewPosition(new Point(0, (pos + 480)));
}

i creating new jpanels using loop. but how i using different object
name.
use JPanel.get/putClientProperty,
you can to multiply this method
every events this/these value, e.g. from Listeners
for example

You are using absolute coordinates, a layout manager gives a better GUI across platforms, later Windows versions, accessibility etcetera.
MainConfig.page21.setLayout(new BoxLayout(MainConfig.page21, BoxLayout.Y_AXIS));
Also normally one would not need the JPanel, an event listener would know how to retrieve the panel.
Nevertheless you could maintain an array of JPanels:
List<JPanel> panels = new ArrayList<>();
In addPanel create a local variable, and add that
public void addNewPanel(int y, String title) { // Not static
JPanel panel = new JPane();
...
panels.add(panel);
}

Related

Creating JPanels with a titled border in a for loop from user input

I want to create a for loop that creates JPanel containers with titled headers. the number of iterations depends on the user input from previous interfaces.
int noofpara=Integer.parseInt(data[6]);
for(int i=1;i<=noofpara;i++){
jPanel1.add(new JPanel().setBorder(new TitledBorder("Perimeter"+i)));
}
The noofpara is the number of perimeters the user chose according to that the for loop should create panels with the titled border with the number of perimeters. the error appears at the jpanel1.add... where it says void type not allowed.
JPanel#setBorder method has void return type, which mean it doesn't return any value when that method invoked.
But JPanel#add method need a value in order to invoked, it gives compilation error since setBorder is void.
You can simply fix this by this.
JPanel childPanel = new JPanel();
childPanel.setBorder(new TitledBorder("Perimeter" + i));
jPanel1.add(childPanel);
You have to make new panel and add.
for (int i = 1; i <= noofpara; i++) {
JPanel innerPane = new JPanel();
innerPane.setBorder(new TitledBorder("Perimeter" + i));
jPanel1.add(innerPane);
}

How to create multiple buttons that do the same on different positions without creating actual new buttons?

Im really new to java and Programming as a whole. In school, I decided to work on a project to raise my grade, and as simple java is currently our topic i decided on trying to recreate battleships in a jframe using swing. I've made some good progress so far but im stuck on a quality of Life Problem.
So basically, in the editor we use (Java Editor ( javaeditor.org )) i use swing to implement buttons etc. in the jframe. As im gonna need a lot of Buttons for the games gui, I want to do it, so i dont have to make several buttons which have to be filled in with the arguments. What im trying to do is have some arguments create several buttons for me so they dont actually all need their own “method“ as all buttons have to basically do the exact same thing.
I tried searching for similar things on google but I couldnt find anything, so i decided to create this account to ask if someone might be able to help me with this Problem. If something isnt understandable feel free to ask (English isnt my mother tongue so some parts might be hard to understand).
Looking forward to any replies! Thanks in advance for helping.
Initially I thought I could use a for-loop to create these multiple buttons but there would always be some kind of error with the ActionPerformed argument.
for (int i = 0;i > 25;i++ ) {
jButton[i].setBounds(48, 48 + i, 113, 73);
jButton[i].setText("jButton1");
jButton[i].setMargin(new Insets(2, 2, 2, 2));
jButton[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton[i]_ActionPerformed(evt);
}
});
cp.add(jButton[i]);
}
As already said I expect there to be more than 1 button, whilst keeping the lines of code in the constructor as short as possible.
If you're desiring a grid of buttons, then create them in a for loop, and place them in the JPanel using a GridLayout. Something like this might work:
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class ManyButtons extends JPanel {
private static final int SIDES = 10;
private JButton[][] buttonGrid = new JButton[SIDES][SIDES];
public ManyButtons() {
setLayout(new GridLayout(SIDES, SIDES));
for (int row = 0; row < buttonGrid.length; row++) {
for (int col = 0; col < buttonGrid[row].length; col++) {
String text = String.format("[%d, %d]", col + 1, row + 1);
buttonGrid[row][col] = new JButton(text);
buttonGrid[row][col].addActionListener(event -> {
String command = event.getActionCommand();
System.out.println("Button pressed: " + command);
});
add(buttonGrid[row][col]);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
ManyButtons mainPanel = new ManyButtons();
JFrame frame = new JFrame("Many Buttons");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
Also avoid setBounds and null layouts.
Regarding:
.... without creating new JButtons
This is not technically possible if you want a fully functioning button (as opposed to creating a rendered button in a JTable), however, buttons can share ActionListeners, so all buttons that do the same kind of thing (think -- all the number buttons on a calculator) can use the very same ActionListener. Alternatively, you can set a button's Action using your own class that extends from AbstractAction for even greater flexibility and power, and multiple buttons (and JMenuItems) can share the same action.

Java Swing clean code with ActionListener

I am trying to make cleaner code in my programs. So I was trying to compress my code to create buttons:
Before, I needed to copy this every single time:
Dimension JButton_Cryption_Size = JButton_Cryption.getPreferredSize();
JButton_Cryption.setBounds(5, 5, JButton_Cryption_Size.width + 50, JButton_Cryption_Size.height);
JButton_Cryption.setFocusPainted(false);
JButton_Cryption.addActionListener(this);
add(JButton_Cryption);
but now I made this method: (Don't pay attention to the button names, they are for testing)
public JButton JButton_Testing1,
JButton_Testing2,
JButton_3;
private void addJButton(JButton ButtonName, String Name, int x, int y, int width, int height, String ToolTip, boolean FocusedPainted, boolean Opaque, boolean ContentAreaFilled, boolean BorderPainted){
ButtonName = new JButton(Name);
Dimension Button_Size = ButtonName.getPreferredSize();
if(width == 0){
ButtonName.setBounds(x, y, Button_Size.width, height);
}if(height == 0){
ButtonName.setBounds(x, y, width, Button_Size.height);
}if(width == 0 && height == 0){
ButtonName.setBounds(x, y, Button_Size.width, Button_Size.height);
}if(width != 0 && height != 0){
ButtonName.setBounds(x, y, width, height);
}
ButtonName.addActionListener(this); // class: implements ActionListener
ButtonName.setToolTipText(ToolTip);
ButtonName.setFocusPainted(FocusedPainted);
ButtonName.setOpaque(Opaque);
ButtonName.setContentAreaFilled(ContentAreaFilled);
ButtonName.setBorderPainted(BorderPainted);
add(ButtonName);
}
private void addButtonToFrame(){
addJButton(JButton_Testing1, "Testing 1", 150, 100, 172, 0, null, false, true, true, true);
addJButton(JButton_Testing2, "Testing 2", 0, 0, 0, 0, null, false, true, true, true);
addJButton(JButton_Testing3, "Testing 3", 200, 150, 250, 100, "YO", false, true, true, true);
}
But when I want to add an action to the button, it wont work
#Override
public void actionPerformed(ActionEvent e){
Object src = e.getSource();
if(src == JButton_Testing1){
System.out.println("yo");
}
}
How can I make so I can keep my thing (or modify it a bit) so I can use the ActionListener correctly
Your question is about clean code, and you ask us to not pay attention to the button names. Half of having clean code is about having good names. Respect the Java conventions, and assign meaningful names to your variables and methods. Variables and methods start with a lowercase character in Java. And they don't contain underscores.
Also, Swing has layout managers. Stop setting bounds. Use layout managers.
Avoid having methods with 11 parameters.
Avoid having public fields. Fields should be private.
And finally, don't use this as the action listener. Use a separate class as your listener.
Regarding your problem: your addJButton() method doesn't add a listener to the button passed as argument. It ignores this argument, creates a new button, and adds the listener to this new button:
public void addJButton(JButton ButtonName, ...) {
ButtonName = new JButton(Name);
A bad strategy is also the addButtonToFrame() method.
It hard codes the number of buttons, their names, and everything. This way if you want to add one more button (for any reason) you have to write one more (custom) line of code to this method.
The right way here is to make an addButtonToFrame(ArrayList <Button> buttons) method. You pass an ArrayList of (as many as you please) buttons in this method. Then add them in the panel, given the objects have been created with Dimension parameter.
But again, this is kind of making a new layout manager, and java has some really nice layout managers. In other words you are reinventing the wheel. That is not always bad (it is a good practice), but to make a good manager you have to spend time and (as I said) there are good managers.
Example:
class ButtonExample{
ArrayList <JButton> buttons = new ArrayList<JButton>();
ActionListener beh = new ButtonEventHandler() //this is a custom class that contains actionPerformed() method
createButtons(){
for (int i = 0; i < buttons.size(); i++)
buttons.get(i) = new JButton();
}
addListeners(){
for (int i = 0; i < buttons.size(); i++)
buttons.get(i).addActionListener(beh);
}
}
The ArrayList is a kind of array without standard size. It is implemented using some nice tricks (that there is no need to know to use it) and you can access its objects with get() method (instead of [] operator like in regular arrays)
The addListeners() and createButtons() methods are dummies just to see how ArrayLists work. You can pass them as parameters in other methods the way you pass any regular object.

JButton not working for me?

I am making a program where you choose a selection sort or a merge sort using JButtons and it sorts an int array in the form of a bar graph using Graphics where each element in the array is a bar.
but for some reason the compiler isn't receiving my button presses, i have tried to use
(selection.equals(e.getSource()) in the if statement but it isnt working, am i missing something obvious or what?
public class Animation extends Canvas implements ActionListener{
JPanel panel;
JButton Selection;
JButton Merge;
boolean selection, merge;
int[] random = new int[25];
Sorter sort = new Sorter();
public Animation(){
Selection = new JButton("Selection sort");
Selection.addActionListener(this);
Selection.setActionCommand("select");
Merge = new JButton("Merge sort");
Merge.addActionListener(this);
Merge.setActionCommand("merge");
panel = new JPanel();
panel.add(Selection);
panel.add(Merge);
setBackground(Color.WHITE);
selection=false;
merge=false;
}
public void actionPerformed(ActionEvent e) {
if("select".equals(e.getActionCommand())){
selection = true;
repaint();
}
else if("merge".equals(e.getActionCommand())){
merge = true;
repaint();
}
}
public void paint (Graphics window){
Random r = new Random();
for(int i=0; i<random.length; i++){
int randomInt = r.nextInt(100) + 1;
random[i] = randomInt;
}
window.setColor(Color.MAGENTA);
if(selection==true){
for(int i=0; i< random.length-1; i++){
int smallest = i;
for(int j = i+1; j< random.length; j++){
if(random[j] < random[smallest])
smallest = j;
}
if( smallest != i) {
int least = random[smallest];
random[smallest] = random[i];
random[i] = least;
drawIt(random, window);
window.setColor(Color.WHITE);
drawIt(random, window);
window.setColor(Color.MAGENTA);
}
}
}
drawIt(random, window);
}
public void drawIt (int[] a, Graphics window1){
int x=128;
int height = 200;
for(int i=0; i<a.length; i++){
window1.drawLine(x, 200, x, height-a[i]);
window1.drawLine(x+1, 200, x+1, height-a[i]);
window1.drawLine(x+2, 200, x+2, height-a[i]);
x+=20;
}
try {
Thread.currentThread().sleep(100);
} catch(Exception ex) {
}
}
}
heres the main class to run it:
public class AnimationRunner extends JFrame{
private static final int WIDTH = 800;
private static final int HEIGHT = 250;
JButton Selection;
JButton Merge;
public AnimationRunner()
{
super("Sorting Animation");
setSize(WIDTH,HEIGHT);
Animation a = new Animation();
Merge = new JButton("Merge sort");
Selection = new JButton("Selection sort");
Merge.setSize(120, 30);
Selection.setSize(120,30);
Merge.setLocation(200, 30);
Selection.setLocation(400, 30);
this.add(Merge);
this.add(Selection);
((Component)a).setFocusable(true);
getContentPane().add(new Animation());
setVisible(true);
}
public static void main( String args[] )
{
AnimationRunner run = new AnimationRunner();
}
}
You create a button for each action in your main class and add these to your JFrame. You also create a two instances of your Animation class. One which you create, setfocusable then do nothing with. Then another which you create and add to the contentPane of the JFrame.
In your Animation constructor you again create a button for each action, this time setting the action commands. You then add these to a panel. This panel is never added to anything and so these buttons will never be seen.
The buttons you see are not the buttons that you have defined the action commands for.
Also you should avoid using setSize() and Use Layout Managers to defines the sizes of your components.
There are a series of cascading problems...
In the AnimationRunner class you create two JButtons called Merge sort and Selection sort and add these to the main frame. This is what's actually on the screen. This buttons have no listeners attached, therefore never notify any body when they are clicked...
In the Animation class you create two JBttonss called Merge sort and Selection sort and add these to panel (and instance of JPanel), which is never added to anything. This means you can never possibly click them...
You don't seem to have an understanding of how painting works in Swing and seem to be assuming that you control the paint process in some way.
Painting is controlled by the paint sub system in Swing, which schedules and performs paint cycles when and where it sees fit. This means that your paint method may be called for any number of reasons, many of which you don't control.
Remove the logic of the sort out of the paint process and place into some kind of model, whose state you can control. Then use the custom painting capabilities to render the state of the model.
paint is an inappropriate method to be using for custom painting and you should be using paintComponent. You have broken the paint chain which may prevent the component from rendering child components and/or introduce series paint artifacts into your program
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
Swing is a single threaded framework work. That means that anything that blocks the Event Dispatching Thread will prevent it from process new repaint requests or events into the system. This will cause your program to look like it's "hung". In your case, you will most likely only ever see the end result of the painting process...after a short delay.
Instead, consider using a javax.swing.Timer to introduce a safe delty and update the model each time it ticks.
Take a look at Concurrency in Swing and How to use Swing Timers for more details
Swing programs are expected to run on a variety of hardware and software platforms, all with there own notions of DPI and font rendering approaches. This makes it very difficult to accommodate your design to all the possible needs of these systems.
Swing makes this easier by providing a layout management API, which takes the fiddle work out of making these decisions. Take a look at Laying Out Components Within a Container for more details
You should also take a look at Code Conventions for the Java Programming Language, it will make it eaiser for people to read your code.
You might find this example of some benifit

Java swing, elements get back on their initial position, after adding new one

I'm trying to write in java program which allows me to creating new controls dynamically, and to move them by mouse.
Right now I can move them, but when i'm creating new one then every object returns to its initial possition. It is quite obvious why - i'm using pack() method on mainframe, but I don't know how to do it otherwise.
Description:
myPanel - my class which extends JPanel
PanelList - ArrayList which contains generated panels
addmyPanel - method shich adds new panel to PanelList
getmyPanel - returns myPanel with certain id
private void jButton0ActionActionPerformed(ActionEvent event) {
myPanel temp = new myPanel();
addmyPanel();
for (int i =0 ;i < PanelList.size(); i++){
temp = PanelList.get(i);
if (!temp.getIsActive()){
try{
add(getmyPanel(temp.getId()), new Constraints(new Leading(35, 100, 10, 10), new Leading(44, 100, 12, 12)));
PanelList.get(i).setIsActive();
}
catch (NoSuchElementException e){}
}
}
frame.pack();
}
Check out Drag Layout. It won't reset the location when the layout manager is invoked.

Categories