|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
[java] database + grafica dubbi
Ciao a tutti, sto creando un'applicazione per la mia parrocchia ma mi trovo con alcuni dubbi. Perciò li scrivo qui che tante volte mi è stato d'aiuto!
Come deve essere il programma alla fine: Un frame principale in cui si aprono dei "sottoprogrammi" I sottoprogrammi sono: - registratore di cassa (legge i cibi dal database, li posiziona in pulsanti che permettono di ricevere delle "comande" da inviare in cucina, fa il totale e interagisce con il database aggiornando i prodotti usciti e i vari ingredienti disponibili). Questo programmino invia a due stampanti e ad un monitor (aggiuntivo, che estende il desktop) le comande. - controllo tavoli (drag and drop e possibilità di posizionare i vari tavoli per vedere graficamente la posizione, ai quali vengono assegnate i vari ordini ricevuti dal primo programma) - server - via tcp/ip comunicazione con app android che permette di avere il "registratore di cassa" su telefono e usarlo a terminale remoto - gestione del database (minimal) Le domande sono queste: Appurato che ogni programma ha la sua classe con i suoi metodi e che lavorare con thread e classi varie non ho problemi, come sarebbe corretto strutturare il tutto tenendo conto della parte grafica? Al momento ho creato una cosa così: programma principale console (classe statica con metodi tipo "Console.print" che scrivono dentro una finestra del programma) e separati: GUI (statica) Menu (che crea il menu della gui) però mi sembra troppo astruso andare e tornare dalle varie classi e ho seri dubbi con la parte grafica. Secondo problema: Il database, sono completamente a digiuno, esiste qualcosa su file oppure devo installare un qualche database sul mac? questi sono i file che ho scritto fino ad adesso: Pagoda.java Codice:
package core; import gui.GUI; public class Pagoda { /** * The name of this program. */ private static final String TITLE = "Cassa Pagoda - vers. 3.0.0"; /** * The GUI */ private static GUI g; /** * The main method * @param arg standard. */ public static void main(String [] arg){ //USE MAC MENUBAR System.setProperty("apple.laf.useScreenMenuBar", "true"); new Console(null); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { Pagoda.g = new GUI(TITLE); Console.setGUI(g); } }); } } Codice:
package core; import gui.GUI; public class Console { /** * Progressive number of version */ protected static final String CONSOLE_VERSION = "0.0.1"; private static final String NEW_LINE_FEED = "\n"; private static GUI gui; Console (GUI g){ gui = g; } public static void print(String msg){ if(gui!=null){ gui.writeInConsole(msg); }else{ System.out.print(msg); } } public static void println(String msg){ print(msg + NEW_LINE_FEED); } public static void setGUI(GUI g) { gui = g; } } Codice:
package gui; import java.awt.Container; import java.awt.Font; import java.util.Hashtable; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import core.Console; public class GUI { /** * Main Frame */ private static JFrame mainFrame; /** * Frames' container */ private JDesktopPane desktop; /** * A reference to each frame in the GUI */ private static Hashtable<String, JInternalFrame> intFrames = new Hashtable<String, JInternalFrame>(); JTextArea output; JScrollPane scrollPane; private static int minX = 300; private static int minY = 150; public GUI(String title) { // ########DEBUG Console.println("[GUI] Creating a new Frame"); // ############# mainFrame = new JFrame(title); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // mainFrame.setIconImage(); mainFrame.setSize(minX, minY); // mainFrame.setLocationRelativeTo(null); //USED TO CENTER mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); //########DEBUG Console.println("[GUI] Creating the desktop content pane"); //############# desktop = new JDesktopPane(); mainFrame.setContentPane(desktop); createConsolePane(); desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); // ########DEBUG Console.println("[GUI] Creating and setting the menu"); // ############# Menu menu = new Menu(); mainFrame.setJMenuBar(menu.createMenuBar()); mainFrame.setVisible(true); } private Container createConsolePane() { JInternalFrame intFrame = new JInternalFrame("Console", true, true, true, true); intFrame.putClientProperty("JInternalFrame.frameType", "normal"); //remove shadows intFrame.setSize(100, 50); //min size intFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); desktop.add(intFrame); // Create a scrolled text area. output = new JTextArea(8, 70); output.setFont(new Font("monospaced",Font.PLAIN,10)); output.setEditable(false); output.setLineWrap(true); output.setWrapStyleWord(false); scrollPane = new JScrollPane(output); // Add the text area to the content pane. intFrame.add(scrollPane); intFrame.pack(); intFrame.setVisible(true); intFrames.put("Console",intFrame); return desktop; } public static Hashtable<String, JInternalFrame> getIntFrameList(){ return intFrames; } public void writeInConsole(String msg) { output.append(msg); output.setCaretPosition(output.getDocument().getLength()); } } Codice:
package gui; import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import core.Console; public class Menu implements ActionListener, ItemListener { JTextArea output; JScrollPane scrollPane; /** * The main menu bar */ private JMenuBar menuBar; /** * Each menu */ private JMenu menu; /** * Each submenu; */ private JMenu submenu; /** * Each element of the menu */ private JMenuItem menuItem; /** * Each check-box in the menu */ private JCheckBoxMenuItem cbMenuItem; private static final String NEW_LINE = "\n"; public JMenuBar createMenuBar() { JRadioButtonMenuItem rbMenuItem; // Create the menu bar. menuBar = new JMenuBar(); // Build the first menu. menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); menuBar.add(menu); // a group of JMenuItems menuItem = new JMenuItem("Start new day", KeyEvent.VK_S); // menuItem.setMnemonic(KeyEvent.VK_T); //used constructor instead menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK)); menuItem.addActionListener(this); menu.add(menuItem); // ImageIcon icon = createImageIcon("images/middle.gif"); menuItem = new JMenuItem("Both text and icon");// , icon); menuItem.setMnemonic(KeyEvent.VK_B); menuItem.addActionListener(this); menu.add(menuItem); menuItem = new JMenuItem("icon"); menuItem.setMnemonic(KeyEvent.VK_D); menuItem.addActionListener(this); menu.add(menuItem); // a group of radio button menu items menu.addSeparator(); ButtonGroup group = new ButtonGroup(); rbMenuItem = new JRadioButtonMenuItem("A radio button menu item"); rbMenuItem.setSelected(true); rbMenuItem.setMnemonic(KeyEvent.VK_R); group.add(rbMenuItem); rbMenuItem.addActionListener(this); menu.add(rbMenuItem); rbMenuItem = new JRadioButtonMenuItem("Another one"); rbMenuItem.setMnemonic(KeyEvent.VK_O); group.add(rbMenuItem); rbMenuItem.addActionListener(this); menu.add(rbMenuItem); // a submenu menu.addSeparator(); submenu = new JMenu("A submenu"); submenu.setMnemonic(KeyEvent.VK_S); menuItem = new JMenuItem("An item in the submenu"); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK)); menuItem.addActionListener(this); submenu.add(menuItem); menuItem = new JMenuItem("Another item"); menuItem.addActionListener(this); submenu.add(menuItem); menu.add(submenu); menu.addSeparator(); menuItem = new JMenuItem("Exit", KeyEvent.VK_X); menuItem.addActionListener(this); menu.add(menuItem); // Build second menu in the menu bar. menu = new JMenu("Window"); menu.setMnemonic(KeyEvent.VK_W); menuBar.add(menu); // a group of JMenuItems menuItem = new JMenuItem("Set defaults windows", KeyEvent.VK_D); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.CTRL_MASK)); menuItem.addActionListener(this); menu.add(menuItem); menu.addSeparator(); cbMenuItem = new JCheckBoxMenuItem("Console"); if(GUI.getIntFrameList().get("Console").isVisible()){ cbMenuItem.setSelected(true); }else{ cbMenuItem.setSelected(false); } cbMenuItem.setMnemonic(KeyEvent.VK_C); cbMenuItem.addItemListener(this); menu.add(cbMenuItem); cbMenuItem = new JCheckBoxMenuItem("Tables' Map"); // if(GUI.getIntFrameList().get("Tables").isVisible()){ // cbMenuItem.setSelected(true); // }else{ // cbMenuItem.setSelected(false); // } cbMenuItem.setMnemonic(KeyEvent.VK_M); cbMenuItem.addItemListener(this); menu.add(cbMenuItem); cbMenuItem = new JCheckBoxMenuItem("Cash Desk"); cbMenuItem.setMnemonic(KeyEvent.VK_K); cbMenuItem.addItemListener(this); menu.add(cbMenuItem); return menuBar; } public Container createContentPane() { // Create the content-pane-to-be. JPanel contentPane = new JPanel(new BorderLayout()); contentPane.setOpaque(true); // Create a scrolled text area. output = new JTextArea(5, 30); output.setEditable(false); scrollPane = new JScrollPane(output); // Add the text area to the content pane. contentPane.add(scrollPane, BorderLayout.CENTER); return contentPane; } public void actionPerformed(ActionEvent e) { JMenuItem source = (JMenuItem) (e.getSource()); String action = source.getText(); if (action.equalsIgnoreCase("exit")) { System.exit(0); } String s = "Action event detected." + NEW_LINE + " Event source: " + source.getText() + " (an instance of " + getClassName(source) + ")"; Console.println(s); } public void itemStateChanged(ItemEvent e) { JMenuItem source = (JMenuItem) (e.getSource()); if (source.getText().equalsIgnoreCase("console")) { if (e.getStateChange() == ItemEvent.SELECTED) { GUI.getIntFrameList().get("Console").setVisible(true); } else { GUI.getIntFrameList().get("Console").setVisible(false); } } String s = "Item event detected." + NEW_LINE + " Event source: " + source.getText() + " (an instance of " + getClassName(source) + ")" + NEW_LINE + " New state: " + ((e.getStateChange() == ItemEvent.SELECTED) ? "selected" : "unselected"); Console.println(s); } // Returns just the class name -- no package info. protected String getClassName(Object o) { String classString = o.getClass().getName(); int dotIndex = classString.lastIndexOf("."); return classString.substring(dotIndex + 1); } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = Menu.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } } } Spero di non essere stato poco chiaro o troppo veloce.. |
![]() |
![]() |
![]() |
#2 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
nessuno nessuno?
|
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
Quote:
L'unica cosa per cui per il momento ti rispondo (perchè l'unica che ho decifrato) è riguardante i database. Se per database intendi un database relazione sql (non fare l'errore di pensare che esistano solo quelli) ne esistono molti basati sul singolo file, il più famoso per java è hsqldb, ma esistono anche versioni di sqlite oppure di firebird ed altri ancora. Per il resto tutti i database in java espongono un interfaccia che implementa il protocollo jdbc, cerca questa su google e troverai tutte le risposte che ti servono. Ti posto solo a titolo di esempio un pezzo di codice preso da qui Codice:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Sample { public static void main(String[] args) throws ClassNotFoundException { // load the sqlite-JDBC driver using the current class loader Class.forName("org.sqlite.JDBC"); Connection connection = null; try { // create a database connection connection = DriverManager.getConnection("jdbc:sqlite:sample.db"); Statement statement = connection.createStatement(); statement.setQueryTimeout(30); // set timeout to 30 sec. statement.executeUpdate("drop table if exists person"); statement.executeUpdate("create table person (id integer, name string)"); statement.executeUpdate("insert into person values(1, 'leo')"); statement.executeUpdate("insert into person values(2, 'yui')"); ResultSet rs = statement.executeQuery("select * from person"); while(rs.next()) { // read the result set System.out.println("name = " + rs.getString("name")); System.out.println("id = " + rs.getInt("id")); } } catch(SQLException e) { // if the error message is "out of memory", // it probably means no database file is found System.err.println(e.getMessage()); } finally { try { if(connection != null) connection.close(); } catch(SQLException e) { // connection close failed. System.err.println(e); } } } } Inoltre esiste il potentissimo BerkelyDB.
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
|
![]() |
![]() |
![]() |
#4 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
Provvedo in a breve a spiegarmi meglio, scusate la latitanza ma ero in vacanza senza accesso ad internet.
|
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
Eccomi di nuovo. Cerco di semplificare per punti quello di cui ho bisogno.
Metto in secondo piano il database perchè devo ancora analizzare per bene il messaggio di wizard1993, nel caso avessi problemi tornerò a postare. Primo problema: la grafica del programma (e con grafica non intendo i disegni bensì la struttura, finestre pulsanti frame ecc). Mi è stato detto da qualche guru della programmazione che per lavorare con la grafica si devono seguire dei passaggi per cercare di separare per quanto possibile la parte UI dalla parte di programmazione, io avrei bisogno di capire la teoria che ci sta dietro. Non ho problemi nel scartabellare javadoc vari ecc, però sono sicuro di sbagliare il metodo perchè tutto ciò che scrivo spesso viene mescolato tra grafica, funzioni ecc. Nello specifico nel mio programma vorrei fare una grafica (faccio un'esempio per capirsi) tipo Photoshop cioè con le finestre che si aprono dentro un frame principale ed interagiscono tra loro, oppure come Eclipse, vari riquadri contenenti cose diverse che interagiscono tra loro. Non mi è un problema prendere pezzo per pezzo e scriverlo hard-coded creando la grafica, poi però non so come far interagire i vari pezzi (immagino che creare tutto statico non sia la cosa migliore), viceversa non mi è un problema scrivere tutta la parte "funzionale" e farla andare in modalità testo, solo che poi non riesco ad aggiungere la grafica. I file che ho scritto finora (riga più riga meno, forse ho aggiunto un paio di cose ma non rilevanti) sono nel primo messaggio. Sono stato più chiaro? Sono riuscito a spiegarmi? Attendo i vostri consigli ![]() |
![]() |
![]() |
![]() |
#6 | ||
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
Quote:
Risposta veramente sensata? Parti da quanto detto sopra e troverai da solo quello che il giusto equilibrio che non necessariamente vuol dire separare le funzioni bindate all'interfaccia in una classe separata: può voler dirne anche farlo in 30 oppure farlo in nessuna. QUello che idealmente devi riuscire a fare è per assurdo, poter cancellare i file dell'interfaccia grafica e lasciare un programma completamente funzionante in tutte le sue funzioni, accessibili tramite api di programmazione Quote:
http://docs.oracle.com/javase/tutori...rnalframe.html Se altri domande chiedi
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
||
![]() |
![]() |
![]() |
#7 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
Grazie per la risposta, non ho aggiunto un messaggio perchè aspettavo di leggermi un po' di cose su quello che hai detto.
Per assurdo io potrei tranquillamente scrivere un programma che funzioni solo testuale, con metodi e accessori vari, per poi aggiungere solo in seguito le parti di controller e view? In teoria dovrebbe essere possibile perchè nel model non ci devono essere parti di grafica, mi basterebbe poi adattare i metodi per interagire con la parte di GUI. Fin qui ho capito oppure sono fuori strada? In tal caso procederei con crearmi la parte di gestione dei dati dal database, e solo poi, con la calma e la sicurezza di un programma che funziona, creare la parte di GUI. giusto? |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Apr 2006
Messaggi: 22462
|
Infatti dovresti proprio fare così. Metti di dover trasformare il tuo programma in una web application: se fai nella maniera giusta ti basta riscrivere la parte di interfaccia e basta.
__________________
amd a64x2 4400+ sk939;asus a8n-sli; 2x1gb ddr400; x850 crossfire; 2 x western digital abys 320gb|| asus g1
Se striscia fulmina, se svolazza l'ammazza |
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
Ottimo, ora mi sto concentrando allora sul database, ho scaricato hsqldb, devo dire che con poche righe di codice sono riuscito a farlo funzionare, seguendo un paio di tutorial online e la guida che allegano allo zip.
Però vorrei togliermi qualche dubbio. Innanzitutto posto la classe che ho scritto Codice:
package core; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import org.hsqldb.Server; public class Database { /** * The database server class */ private static Server hsqlServer; /** * The connection class. Used to manage request to the database. */ private Connection connection; /** * Constructor.<br> * Create a new <code>Database</code> connected to a specified hsqldb and saved in a specified file.<br> * Defaults sets logs to null e logWriter to null. * @param dbName The name of the database to connect * @param fileName The name of the file where the database is saved. */ public Database(String dbName, String fileName){ hsqlServer = null; connection = null; // Create a new database server class. hsqlServer = new Server(); // HSQLDB prints out a lot of informations when starting and closing, which we don't need now. Normally you should point the setLogWriter to some Writer object that could store the logs. hsqlServer.setLogWriter(null); hsqlServer.setSilent(true); // The actual database will be named 'xdb' and its // settings and data will be stored in files // testdb.properties and testdb.script hsqlServer.setDatabaseName(0, dbName); hsqlServer.setDatabasePath(0, "file:"+fileName); } public void start(){ hsqlServer.start(); connection = null; } public void stop(){ if (hsqlServer != null) { hsqlServer.stop(); } } public void connect() throws ClassNotFoundException, SQLException { // Getting a connection to the newly started database Class.forName("org.hsqldb.jdbcDriver"); // Default user of the HSQLDB is 'sa' with an empty password connection = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "sa", ""); } public void doSomething() throws ClassNotFoundException, SQLException{ try { // Here we run a few SQL statements to see if // everything is working. // We first drop an existing 'testtable' (supposing // it was there from the previous run), create it // once again, insert some data and then read it // with SELECT query. connection.prepareStatement("drop table testtable;").execute(); connection.prepareStatement("create table testtable ( id INTEGER, " + "name VARCHAR(11));").execute(); connection.prepareStatement("insert into testtable(id, name) " + "values (1, 'testvalue');").execute(); connection.prepareStatement("insert into testtable(id, name) " + "values (2, 'testvalue');").execute(); connection.prepareStatement("insert into testtable(id, name) " + "values (3, 'testvalue');").execute(); ResultSet rs = connection.prepareStatement("select * from testtable;").executeQuery(); // Checking if the data is correct while (!rs.isLast()) { rs.next(); System.out.println("Id: " + rs.getInt(1) + " Name: " + rs.getString(2)); } } finally { // Closing the connection if (connection != null) { connection.close(); } this.stop(); } } public static void main(String[] args) throws ClassNotFoundException, SQLException { // // // 'Server' is a class of HSQLDB representing // // the database server // Server hsqlServer = null; // try { // hsqlServer = new Server(); // // // HSQLDB prints out a lot of informations when // // starting and closing, which we don't need now. // // Normally you should point the setLogWriter // // to some Writer object that could store the logs. // hsqlServer.setLogWriter(null); // hsqlServer.setSilent(true); // // // The actual database will be named 'xdb' and its // // settings and data will be stored in files // // testdb.properties and testdb.script // hsqlServer.setDatabaseName(0, "xdb"); // hsqlServer.setDatabasePath(0, "file:testdb"); // // // Start the database! // hsqlServer.start(); // // Connection connection = null; // // We have here two 'try' blocks and two 'finally' // // blocks because we have two things to close // // after all - HSQLDB server and connection // try { // // Getting a connection to the newly started database // Class.forName("org.hsqldb.jdbcDriver"); // // Default user of the HSQLDB is 'sa' // // with an empty password // connection = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "sa", ""); // // // Here we run a few SQL statements to see if // // everything is working. // // We first drop an existing 'testtable' (supposing // // it was there from the previous run), create it // // once again, insert some data and then read it // // with SELECT query. // connection.prepareStatement("drop table testtable;").execute(); // connection.prepareStatement("create table testtable ( id INTEGER, " + "name VARCHAR(11));").execute(); // connection.prepareStatement("insert into testtable(id, name) " + "values (1, 'testvalue');").execute(); // connection.prepareStatement("insert into testtable(id, name) " + "values (2, 'testvalue');").execute(); // connection.prepareStatement("insert into testtable(id, name) " + "values (3, 'testvalue');").execute(); // ResultSet rs = connection.prepareStatement("select * from testtable;").executeQuery(); // // // Checking if the data is correct // while (!rs.isLast()) { // rs.next(); // System.out.println("Id: " + rs.getInt(1) + " Name: " + rs.getString(2)); // } // } finally { // // Closing the connection // if (connection != null) { // connection.close(); // } // // } // } finally { // // Closing the server // if (hsqlServer != null) { // hsqlServer.stop(); // } // } Database d = new Database("xdb","testdb"); d.start(); d.connect(); d.doSomething(); d.stop(); } } Vorrei innanzitutto sapere se sono lecite le modifiche che ho fatto, creando costruttore, metodi d'accesso ecc che userò nelle altre classi, nello specifico il mio dubbio sta in questo: Codice:
Database d = new Database("xdb","testdb"); d.start(); d.connect(); d.doSomething(); d.stop(); Seconda domanda. Vorrei una conferma sul fatto che ho verificato che il database NON viene creato ogni volta nuovo, io ho capito che: se c'è, si collega se non c'è lo crea e poi si collega. Giusto? Leggevo prima le query che vengono inserite, io arrivo da esperienze con MySQL, ma non mi sembra la stessa cosa, che nome ha il linguaggio che usa questa libreria?? |
![]() |
![]() |
![]() |
#10 |
Member
Iscritto dal: Sep 2010
Messaggi: 102
|
Attualmente ho creato una classe che gestisce la grafica e quindi l'internal frame del mio "registratore di cassa"
è giusto che per crearsi legga lei stessa nel database? oppure devo farlo fare alla classe delle azioni? quando invece devo fare il catch di un evento a pulsante, stavo pensando di utilizzare un metodo che richiami nella classe delle azioni l'azione appropriata. però in questo modo nel costruttore della GUI devo passargli l'oggetto gestore delle azioni. altrimenti non lo posso referenziare. è giusto il ragionamento che sto facendo? |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:46.