Accessing JFrame stuff from the outside

梦想与她 提交于 2020-01-06 12:58:28

问题


Really, really stupid question here. I'm new to Java (and OOP), coming from a Javascript (Extendscript, actually) background. I have a JFrame here:

package info.chrismcgee.sky.production;

import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXTreeTable;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

public class ProductionWindow extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = -1899673458785493250L;
    private JPanel contentPane;
    private JTextField textField;
    private JLabel lblTodaysDate;
    private JXTreeTable treeTable;

    /**
     * Create the frame.
     */
    public ProductionWindow() {
        setMinimumSize(new Dimension(450, 300));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new MigLayout("", "[][grow,center][]", "[][grow][]"));

        JButton btnPrev = new JButton("<- PREV");
        contentPane.add(btnPrev, "cell 0 0,alignx left");

        lblTodaysDate = new JLabel("Today's Date");
        lblTodaysDate.setHorizontalAlignment(SwingConstants.CENTER);
        lblTodaysDate.setFont(new Font("Lucida Grande", Font.PLAIN, 20));
        contentPane.add(lblTodaysDate, "cell 1 0,growx");

        JButton btnNext = new JButton("NEXT ->");
        contentPane.add(btnNext, "cell 2 0,alignx right");

        treeTable = new JXTreeTable();
        treeTable.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
        contentPane.add(treeTable, "cell 0 1 3 1,grow");

        JLabel lblTotal = new JLabel("Total:");
        lblTotal.setFont(new Font("Lucida Grande", Font.PLAIN, 24));
        contentPane.add(lblTotal, "cell 0 2");

        textField = new JTextField();
        textField.setEditable(false);
        textField.setHorizontalAlignment(SwingConstants.RIGHT);
        textField.setFont(new Font("Lucida Grande", Font.PLAIN, 24));
        textField.setText("1,000");
        contentPane.add(textField, "cell 1 2 2 1,growx");
        textField.setColumns(10);
    }

    public JPanel getContentPane() {
        return contentPane;
    }

    public void setContentPane(JPanel contentPane) {
        this.contentPane = contentPane;
    }

    public JTextField getTextField() {
        return textField;
    }

    public void setTextField(JTextField textField) {
        this.textField = textField;
    }

    public JLabel getLblTodaysDate() {
        return lblTodaysDate;
    }

    public void setLblTodaysDate(String today) {
        this.lblTodaysDate.setText(today);
    }

    public JXTreeTable getTreeTable() {
        return treeTable;
    }
}

I then call this code from a Main class:

package info.chrismcgee.sky.production;

import info.chrismcgee.sky.production.tables.JobManager;
import info.chrismcgee.sky.production.tables.ShowJobs;
import info.chrismcgee.util.InputHelper;

import java.awt.EventQueue;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import org.apache.commons.io.FileUtils;
import org.joda.time.LocalDate;

public class Main {

    // This enum will call a stored procedure which returns all of a certain day's jobs.
    public static final String SQL_JOBS_BY_DATE = "{CALL GetJobsWithCountByDate(?, ?)}";

    private static Connection conn = ConnectionManager.getInstance().getConnection();

    public static void main(String[] args) throws Exception {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ProductionWindow frame = new ProductionWindow();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        ConnectionManager.getInstance().setDBType(DBType.MYSQL);

        JobManager.displayAllRows();

        LocalDate searchDate = new LocalDate(2014, 01, 02);
        Date sqlDate = Date.valueOf(searchDate.toString());

        ResultSet rs = null;
        try (
                // Create a statement object. (Defines how the result set is handled.)
                CallableStatement stmt = conn.prepareCall(
                        SQL_JOBS_BY_DATE,
                        ResultSet.TYPE_FORWARD_ONLY,
                        ResultSet.CONCUR_READ_ONLY);
                ) {
            // Create the result set for today.
            stmt.setDate(1, sqlDate);
            stmt.registerOutParameter("total", Types.INTEGER);
            rs = stmt.executeQuery();

            int nRows = stmt.getInt("total");

            ShowJobs.displayData(rs, nRows);

            ShowJobs.getTodaysJobs(rs, nRows, ProductionWindow, textField);

        } catch (SQLException e) {
            // In case there is some error with the database.
            ConnectionManager.processException(e);
        } finally {
            rs.close();
        }

        ConnectionManager.getInstance().close();

    }

}

This is still in development; haven't even tested it yet. My problem is accessing ProductionWindow's methods from the Main class. Eclipse doesn't let me choose the getTreeTable() method when I press [CTRL]-[SPACE] after typing ProductionWindow. in that ShowJobs.getTodaysJobs line near the end of Main.

I know there's an obvious answer for this, a good reason, etc., as well as solution to make it work that is more "proper" in Java. I just don't know any of this because I'm still new to Java and OOP.


回答1:


Judging by this question and some of your others, you seem to have a specific idea about these windows having to be very simple with no code in them, which then get manipulated externally by other classes. This is not what Swing (or even Java) is about.

Think of the JFrames and JDialogs as rooms in your house. You wouldn't set up your kitchen with all the right utensils and then go into the dining room and try to work the stove remotely!

If a window's job is to populate a table in the screen, update the table and deal with user input related to the table, then all of that code should be inside the Window's class (whether its a JFrame or a JDialog).

Think about focus. If the user's focus and input is inside a Window, then the code to deal with that should also be inside that Window.

This is one of the most fundamental OOP principles: Encapsulation




回答2:


The problem is that getTreeTable() is not a static method, and hence cannot be accessed by the class name (ProductionWindow.getTreeTable()). You need an object's handle to do this.

In your run(), when you are declaring a new "frame", store that in a class level attribute in Main class. Then use "frame.getTreeTable()". To demonstrate, write "frame." right after you declare "frame", and then press ctrl+space. You will get a lot of methods there.



来源:https://stackoverflow.com/questions/21145911/accessing-jframe-stuff-from-the-outside

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!