Swing, pierwszy program

0

Witam, piszę swój pierwszy program w Swingu, i napisałem wszystko ale nie mam pojecia jak zrobić mechanikę

1.Nie wiem jak zrobic by pojedynczych liczb podawać ich więcej
2.Teraz jak wcisne 3 to zapisze do zmiennej 3 ( w fazie projektowania) ale jak zrobić tak by móc jeszcze znak i druga liczbe wpisać.

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class Kalkulator extends JFrame implements ActionListener{

    JButton jeden,dwa,trzy,cztery,piec,szesc,siedem,osiem,dziewiec;
    JButton plus,minus,mnozenie,dzielenie;
    JLabel lsiema,lwynik;

    
    public Kalkulator(){



        setSize(800,500);
        setTitle("Kalkulator");
        setLayout(null);

        jeden = new JButton("1");
        jeden.setBounds(60,240,60,60);
        add(jeden);
        jeden.addActionListener(this);
        dwa = new JButton("2");
        dwa.setBounds(125,240,60,60);
        add(dwa);
        dwa.addActionListener(this);
        trzy = new JButton("3");
        trzy.setBounds(190,240,60,60);
        add(trzy);
        trzy.addActionListener(this);
        cztery = new JButton("4");
        cztery.setBounds(60,175,60,60);
        add(cztery);
        cztery.addActionListener(this);
        piec = new JButton("5");
        piec.setBounds(125,175,60,60);
        add(piec);
        piec.addActionListener(this);
        szesc = new JButton("6");
        szesc.setBounds(190,175,60,60);
        add(szesc);
        szesc.addActionListener(this);
        siedem = new JButton("7");
        siedem.setBounds(60,110,60,60);
        add(siedem);
        siedem.addActionListener(this);
        osiem = new JButton("8");
        osiem.setBounds(125,110,60,60);
        add(osiem);
        osiem.addActionListener(this);
        dziewiec = new JButton("9");
        dziewiec.setBounds(190,110,60,60);
        add(dziewiec);
        dziewiec.addActionListener(this);
        plus = new JButton("+");
        plus.setBounds(300,110,60,60);
        add(plus);
        plus.addActionListener(this);
        minus = new JButton("-");
        minus.setBounds(300,175,60,60);
        add(minus);
        minus.addActionListener(this);
        mnozenie = new JButton("*");
        mnozenie.setBounds(300,240,60,60);
        add(mnozenie);
        mnozenie.addActionListener(this);
        dzielenie = new JButton("/");
        dzielenie.setBounds(300,305,60,60);
        add(dzielenie);
        dzielenie.addActionListener(this);

        lsiema = new JLabel("");
        lsiema.setBounds(500,0,300,300);
        add(lsiema);

        lwynik = new JLabel("wynik");
        lwynik.setBounds(600,0,300,300);
        add(lwynik);




    }
    public static void main(String[] args){

        Kalkulator okienko = new Kalkulator();
        okienko.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        okienko.setVisible(true);

    }
    public void actionPerformed(ActionEvent e){

        Object zrodlo = e.getSource();
        if(zrodlo==jeden){
            lsiema.setText("1");
        }
        else if (zrodlo==dwa){
            lsiema.setText("2");
        }
        else if(zrodlo==trzy){
            lsiema.setText("3");
        }
        else if(zrodlo==cztery){
            lsiema.setText("4");
        }
        else if(zrodlo==piec){
            lsiema.setText("5");
        }
        else if(zrodlo==szesc){
            lsiema.setText("6");
        }
        else if(zrodlo==siedem){
            lsiema.setText("7");
        }
        else if(zrodlo==osiem){
            lsiema.setText("8");
        }
        else if(zrodlo==dziewiec){
            lsiema.setText("9");
        }

    }
}
1

Nie napisałes właściwie nic, a to co napisałes nadaje się tylko do skasowania.
Lekcja na dziś: tablice (robienie 10 zmiennych z buttonami, szczególnie takimi jak te tutaj to jest jakaś abominacja...)

0

Po pierwsze moim zdanem do rysowania siatki przycisków powinieneś skorzystać z GridLayout:

http://docs.oracle.com/javase/tutorial/uiswing/layout/grid.html

Poza tym aby dodać cyfry do liczby powinieneś użyć:
lsiema.setText(lsiema.getText() + "1");

Poczytaj też o MVC aby oddzielić logikę działania aplikacji od widoku. No i tak jak kolega wyżej napisał poczytaj o tablicach, aby nie tworzyć na sztywno każdego przycisku, poniweaż jakbyś miał siatkę 10 x 10 to trochhę by zeszeło z wypisaniem kodu tworzącego przyciski + podanie prawidłowych rozmiarów i współrzędnych dla przycisków.

0

Zacznij od rozwiązania tych problemów które pokazaliśmy. Wszystko w swoim czasie. Jak już te problemy rozwiążesz do odkryjesz że zamiast sztywnego setText(cośtam) możesz dać edit.setText(edit.getText()+nowa_cyferka)...

0

dużo pracy przede mną, robie te programy oglądając w między czasie kurs na yt

0

Poczytaj o layoutach w Swing'u oraz o tym jak używać tablic + ActionListenerów aby nie było czegoś takiego jak:

if(source == bt1) {
// instrukcja
} else if (source == bt2) {
// instrukcja
}

etc...
To można załatwić w kilku linijkach a nie w 30-40. Poza tym stwórz sobie metodę która towrzy przyciski a przyjmuję Stringa z etykietą przycisku.

0

Nie wiem czy już to pisałem ale dopiero zaczynam

0

Wiemy, ale dobrze już od razu nabierać prawidłowych praktyk, stąd nasze komenarze :)

0

Znalazłem taki kod, przeanalizowałem i wydaje mi się że rozumiem już

import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class Kalkulator extends JFrame {

    public Kalkulator() {

        initUI();
    }

    public final void initUI() {

        JPanel panel = new JPanel();

        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panel.setLayout(new GridLayout(5, 5, 5, 5));

        String[] buttons = {
                "Cls", "Bck", "x", "Close", "7", "8", "9", "/", "4",
                "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+"
        };


        for (int i = 0; i < buttons.length; i++) {

            if (i == 2)
                panel.add(new JLabel(buttons[i]));
            else
                panel.add(new JButton(buttons[i]));
        }

        add(panel);

        setTitle("GridLayout");
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                Kalkulator ex = new Kalkulator();
                ex.setVisible(true);
            }
        });
    }
}

teraz w jaki sposób wpleść w to mechanike

2

No bez sensu to zrobiłeś. Jak tworzysz button to od razu mu nadaj action listenera.
Ale powinienes to generować w kilku pętlach bo buttony z cyferkami będą miały jednego action listenera (zależnego od parametru) a buttony *, / czy = będą mialy swoje własne.

0
Shalom napisał(a):

No bez sensu to zrobiłeś. Jak tworzysz button to od razu mu nadaj action listenera.

.addActionListener(this);

tak czy w inny sposób? Tak będzie mi łatwiej później wartości pobrac

0

Nie, nie tak. NIE PISZEMY klas typu "człowiek orkiestra". Jak coś jest JFrame to nie jest już ActionListenerem. Zrób osobną klasę dla tego action listenera...

1
BartoszCoyote napisał(a):

.addActionListener(this);

tak czy w inny sposób? Tak będzie mi łatwiej później wartości pobrac

Poczytaj o wzorcu projektowym MVC- model, widok, kontroler. We frame powinien być tylko widok, a logika czyli ActionListener w kontrolerze.

0

@Shalom nie wiem jak napisać to, w necie szukałem i wszystkie programy napisane są według tego jak ja napisałem

2

No to jak nie wiesz to porzuć okienka i kalkulatory i wróć do podstaw javy. Bo skoro nie umiesz napisać klasy implementującej dany interfejs, to znaczy że coś jest nie tak i przeskoczyłeś połowę kursu/książki.

0

A to już pytając poważnie to lepiej tworzyć klasy zagnieżdzone a jeżeli zupełnie oddzielne to w jaki sposób łatwo przekazać referencje do wszystkich obiektów słuchanych. przy klasie zagnieżdżonej nie ma problemu bo można to zrobić łatwo i szybko

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package listenerchange;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
 *
 * @author w.maciejewski
 */
public class JOkno extends JFrame {
    private final sluchacz sl;
    JButton but,but1;
   
   public JOkno(){
   
    setSize(300,300);
    but=new JButton("1");
    but1=new JButton("2");
    sl=new sluchacz();
    
    but.addActionListener(sl);
    but1.addActionListener(sl);
    setLayout(new FlowLayout());
    add(but);
    add(but1);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
        
   }
 
   
   
   
   class sluchacz implements ActionListener{
        
  
        @Override
        public void actionPerformed(ActionEvent ae) {
            if(ae.getSource()==but){
                System.out.print("dupa 1");
            }else if(ae.getSource()==but1){
                System.out.print("dupa 2");
            }
            
        }
       
   } 
}

ale nie bardzo se wyobrażam jak to zrobić przy zupełnie oddzielnej klasie

1

Przekazuj referencję do obiektu klasy, a nie do poszczególnych pól.

public  class Sluchacz implements ActionListener{
    private Nadawca nadawca; 
    public Sluchacz(Nadawca nadawca)
    {
        this.nadawca = nadawca;
    }
     @Override
     public void actionPerformed(ActionEvent ae) {
         if(ae.getSource()==nadawca.but){
                System.out.print("dupa 1");
            }else if(ae.getSource()==nadawca.but1){
                System.out.print("dupa 2");
            }
 
      }
 }

A w klasie nadawcy

.addActionListener(new Sluchacz(this)));
0

w taki sposób?


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package listenerchange;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
 *
 * @author w.maciejewski
 */
public class JOkno extends JFrame {
    private final sluchacz sl;
    JButton but,but1;
   
   public JOkno(){
   
    setSize(300,300);
    but=new JButton("1");
    but1=new JButton("2");
    sl=new sluchacz(this);
    
    but.addActionListener(sl);
    but1.addActionListener(sl);
    setLayout(new FlowLayout());
    add(but);
    add(but1);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
        
   }
 
   
   
   
  
}
 class sluchacz implements ActionListener{
  JOkno jo;      
  sluchacz(JOkno jo1){
      jo=jo1;
  }
        @Override
        public void actionPerformed(ActionEvent ae) {
            if(ae.getSource()==jo.but){
                System.out.print("dupa 1");
            }else if(ae.getSource()==jo.but1){
                System.out.print("dupa 2");
            }
            
        }
       
   } 
0

OMG. Zrób KILKA action listenerów skoro ich akcje są różne, a nie jeden z drabinką ifów. Znów: zasada jednej odpowiedzialności, tym razem w kontekście metody. Jedna metoda robi jedna rzecz. A nie 700 w zalezności od ifa.

0

Okey bo się bałagan robi w tych komentarza.

Gjorni przeczytałem, okey wszystko zrozumiałem, zrobić tak żeby było łatwo rozszerzyć a nie modyfikować. ok
Moje ostatnie pytanie jest takie czy zrobić klasę słuchającą 2 róznych zdarzeń robiących de facto to samo czy napisać 2 klasy. Wydaje mi się że łatwiej (mniej kodu i bardziej zwięzłe ) będzie coś takiego

class sluchacz1 implements ActionListener, KeyListener{
KeyEvent dobry_przycisk;

    @Override
    public void actionPerformed(ActionEvent ae) {
        metoda();
    }

    @Override
    public void keyTyped(KeyEvent ke) {
        if(ke.getKeyCode()==dobry_przycisk){
              metoda();
        }
       
    }
    @Override
    public void keyPressed(KeyEvent ke) {   
    }
    @Override
    public void keyReleased(KeyEvent ke) {    
    }

    
    private void metoda(){
        //zrob tutaj cos
    }
  }
      

czy robić też zupełnie oddzielną klasę do KeyListenera co się wydaje bez sensu

1

Jeśli akcja jest taka sama, to możesz zamknąć to w jednej klasie, ale ja bym tam jednak dał extends KeyAdapter a nie zostawiał puste metody...

0

A co myślicie o takim kodzie? Chodzi o przesyłanie komponentów z widoku do kontrolera? Ja tak zawsze robię w prostych progamach Swing ale zastanawiam się czy to odpowiedni sposób :) Wszystkie potrzebne komponenty, które będą zmieniane wysyłam do kontrolera/ presentera.


package mvc.view;

import mvc.controller.MainFramePresenter;

import javax.swing.*;
import java.awt.*;

/**
 * Author: Daniel
 */
public class MainFrame extends JFrame {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 300;

    public MainFrame() {
        setUpFrame();
        initializeComponentst();
    }

    private void setUpFrame() {
        setTitle("Test");
        setSize(new Dimension(WIDTH, HEIGHT));
        setLocationRelativeTo(null);
    }

    private void initializeComponentst() {
        MainFramePresenter presenter = new MainFramePresenter();

        MainPanel mainPanel = new MainPanel();
        add(mainPanel);

        presenter.setButton(mainPanel.getButton());
    }
}

// *****************************************************************************************

package mvc.view;

import javax.swing.*;

/**
 * Author: Daniel
 */
public class MainPanel extends JPanel {
    private JButton button;

    public MainPanel() {
        initliazeComponents();
    }

    private void initliazeComponents() {
        button = new JButton("Kliknij");
        add(button);
    }

    public JButton getButton() {
        return button;
    }
}

// *****************************************************************************************

package mvc.controller;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Author: Daniel
 */
public class MainFramePresenter {

    class ButtonLister implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Kliknięto");
        }
    }

    public void setButton(JButton button) {
        button.addActionListener(new ButtonLister());
    }
}

// *****************************************************************************************

package mvc;

import mvc.view.MainFrame;

import javax.swing.*;
import java.awt.*;

/**
 * Author: Daniel
 */
public class Main {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MainFrame mainFrame = new MainFrame();
                mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                mainFrame.setVisible(true);
            }
        });
    }
}

 
0

Nikt nie potrafi ocenić czy podejście przesyłania w ten sposób komponentów do Presentera jest prawidłowe?

1 użytkowników online, w tym zalogowanych: 0, gości: 1