मैं एक जावाएफएक्स सुडोकू प्रोग्राम लिखने की कोशिश कर रहा हूं जहां उपयोगकर्ता एक सेल भर सकता है:

  1. नौ बटनों में से एक पर क्लिक करना (1-9 के अनुरूप)
  2. किसी एक सेल पर क्लिक करना

जिस तरह से कोड काम करता है वह यह है कि जब एक बटन क्लिक किया जाता है, तो उस बटन से संबंधित int selectedNum को असाइन किया जाता है। और जब सेल पर क्लिक किया जाता है, तो सेल अपना टेक्स्ट selectedNum को असाइन कर देता है। हालाँकि, यह वह जगह है जहाँ समस्या होती है - Cell कंस्ट्रक्टर के अंदर setOnAction फ़ंक्शन को लागू करने में। Cell, selectedNum तक नहीं पहुंच सकते। जब मैं अपनी कक्षा के दायरे से बाहर एक चर है तो मैं चयनित संख्या कैसे पास कर सकता हूं?

सेल क्लास:

import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

/**
 * The Cell class inherits StackPane, representing one of the cells in Sudoku.
 * @author rkuni
 *
 */
public class Cell extends StackPane{
    
    private Text text; //displays the number inside the cell
    private Rectangle rect; //visual element for the cell
    
    /**
     * Default Constructor for Cell
     */
    public Cell() {
        text = new Text("");
        text.setFont(Font.font(30));
        rect = new Rectangle(50, 50);
        rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
        this.getChildren().add(rect);
        this.getChildren().add(text);
        
        this.setOnMouseClicked(new EventHandler<MouseEvent>() { 
            @Override
            public void handle(MouseEvent t) {
                text.setText("" + 1); //when clicked, I want to set text to the number that is selected.
            }
        });
    }
}

मुख्य कक्षा

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;

public class Main extends Application {
    
    private int selectedNum = 0;
    
    @Override
    public void start(Stage primaryStage) {
        try {
            
            Group root = new Group();
            Cell cell1 = new Cell();
            cell1.setLayoutX(100);
            cell1.setLayoutY(100);
            root.getChildren().add(cell1);
            
            Button numSelection[] = new Button[9];
            for (int i = 0; i < 9; i++) {
                final int j = i; 
                numSelection[i] = new Button("" + (i + 1));
                numSelection[i].setLayoutY((i / 3) * 55 + 200);
                numSelection[i].setLayoutX((i % 3) * 55 + 630);
                numSelection[i].setMinHeight(50);
                numSelection[i].setMinWidth(50);
                numSelection[i].setFont(Font.font(20));
                root.getChildren().add(numSelection[i]);

                numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        selectedNum = j + 1;
                    }
                });
            }
            
            Scene scene = new Scene(root,900,500);
            primaryStage.setScene(scene);
            primaryStage.show();
            
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

संभावित समाधान

एक संभावित समाधान सेल क्लास बिल्कुल नहीं है, और कोड काम करेगा। समस्या अब नहीं है क्योंकि सभी चर एक ही दायरे में हैं। हालांकि, मैं सेल क्लास रखना चाहता हूं क्योंकि यह अधिक संगठित कोड बनाता है। यहाँ यह वैसे भी है:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;


public class Main extends Application {
    
    private int selectedNum; //will take the value of the last pressed button (1-9)
    
    @Override
    public void start(Stage primaryStage) {
        try {
            Group root = new Group();
            
            //setting up a stackpane that will contain a rect and text, making for a "cell"
            StackPane stack1 = new StackPane();
            Text text1 = new Text("");
            Rectangle rect1 = new Rectangle(50,50);
            rect1.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
            stack1.getChildren().add(text1);
            stack1.getChildren().add(rect1);
            stack1.setLayoutX(100);
            stack1.setLayoutY(100);
            stack1.setOnMouseClicked(new EventHandler<MouseEvent>() { 
                @Override
                public void handle(MouseEvent t) {
                    text1.setText("" + selectedNum); //when clicked, set text to the number that is selected.
                }
            });
            
            //setting up the buttons that will designate which number will go into the cell.
            Button numButtons[] = new Button[9];
            for (int i = 0; i < 9; i++) {
                final int j = i;
                numButtons[i] = new Button("" + (i + 1));
                numButtons[i].setLayoutY((i / 3) * 55 + 200);
                numButtons[i].setLayoutX((i % 3) * 55 + 630);
                numButtons[i].setMinHeight(50);
                numButtons[i].setMinWidth(50);
                numButtons[i].setFont(Font.font(20));
                root.getChildren().add(numButtons[i]);

                numButtons[i].setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        selectedNum = j + 1;
                    }
                });
            }
            
            text1.toFront();
            root.getChildren().add(stack1);
            Scene scene = new Scene(root,900,500);
            primaryStage.setScene(scene);
            primaryStage.show();
            
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

मैंने पैरामीटर जोड़ने के लिए फ़ंक्शन को ओवरराइड करने के बारे में भी सोचा है लेकिन इसे सफलतापूर्वक काम करने के लिए नहीं मिला है।

0
Roy K. 16 पद 2020, 18:09
ऐसा करने के कई तरीके हैं। आप या तो Cell में कोई ईवेंट प्रकाशित कर सकते हैं और उसे Main में पकड़ सकते हैं। या आप सेल को एक नई फ़ंक्शन प्रॉपर्टी दे सकते हैं, जिसे आपके mouseclicked इवेंटहैंडलर में कहा जाता है। आप इसे अपने Main वर्ग के कंस्ट्रक्टर के अंदर सेट कर सकते हैं
 – 
Amir Schnell
16 पद 2020, 18:53
या चयनित मान रखने के लिए अपनी मुख्य कक्षा में एक IntegerProperty बनाएं, और इसे अपने Cell को पास करें।
 – 
James_D
16 पद 2020, 19:26

1 उत्तर

सबसे बढ़िया उत्तर

इस तरह की चीजों के लिए (अधिक या कम) मानक दृष्टिकोण एमवीसी डिजाइन पैटर्न के किसी प्रकार के संस्करण का उपयोग करना है। यहां महत्वपूर्ण बात यह है कि एक अलग वर्ग ("मॉडल") है जो डेटा रखता है; फिर आप उस वर्ग का एक उदाहरण किसी भी अभिनेता को पास कर सकते हैं जिसे उस तक पहुंच की आवश्यकता है।

public class Model {

    private int currentlySelectedValue ;

    // probably other properties here...

    public void setCurrentlySelectedValue(int value) {
        currentlySelectedValue = value ;
    }

    public int getCurrentlySelectedValue() {
        return currentlySelectedValue ;
    }
}

तब आप कर सकते हैं:

public class Cell extends StackPane{

    private final Model model ;
    
    private Text text; //displays the number inside the cell
    private Rectangle rect; //visual element for the cell
    
    /**
     * Default Constructor for Cell
     */
    public Cell(Model model) {
        this.model = model ;
        text = new Text("");
        text.setFont(Font.font(30));
        rect = new Rectangle(50, 50);
        rect.setStyle("-fx-fill: white; -fx-stroke: black; -fx-stroke-width: 1;");
        this.getChildren().add(rect);
        this.getChildren().add(text);
        
        this.setOnMouseClicked(new EventHandler<MouseEvent>() { 
            @Override
            public void handle(MouseEvent t) {
                text.setText("" + model.getCurrentlySelectedValue()); 
            }
        });
    }
}

तथा

public class Main extends Application {
    
    private int selectedNum = 0;
    
    @Override
    public void start(Stage primaryStage) {

        Model model = new Model();

        try {
            
            Group root = new Group();
            Cell cell1 = new Cell(model);
            cell1.setLayoutX(100);
            cell1.setLayoutY(100);
            root.getChildren().add(cell1);
            
            Button numSelection[] = new Button[9];
            for (int i = 0; i < 9; i++) {
                final int j = i + 1; 
                numSelection[i] = new Button("" + j);
                numSelection[i].setLayoutY((i / 3) * 55 + 200);
                numSelection[i].setLayoutX((i % 3) * 55 + 630);
                numSelection[i].setMinHeight(50);
                numSelection[i].setMinWidth(50);
                numSelection[i].setFont(Font.font(20));
                root.getChildren().add(numSelection[i]);

                numSelection[i].setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        model.setCurrentlySelectedValue(j);
                    }
                });
            }
            
            Scene scene = new Scene(root,900,500);
            primaryStage.setScene(scene);
            primaryStage.show();
            
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

ध्यान दें कि कुछ "शॉर्टकट" दृष्टिकोण हैं यदि आपको केवल एक ही मान की आवश्यकता है; जैसे आप कस्टम मॉडल वर्ग के बजाय IntegerProperty का उपयोग कर सकते हैं। हालांकि संरचना और अवधारणा वास्तव में वही है।

2
James_D 16 पद 2020, 19:37
तो यह जावा में संदर्भों का प्रदर्शन है? प्रत्येक सेल में एक Model ऑब्जेक्ट होता है जो model के अंदर Main का संदर्भ होता है। और जैसे ही selectedNum में model बदलता है, प्रत्येक सेल के पास इसका उपयोग होता है क्योंकि उनके पास इसका एक संदर्भ होता है। वाह, इसने मेरा दिमाग उड़ा दिया।
 – 
Roy K.
16 पद 2020, 22:00
क्या MVC डिज़ाइन पैटर्न JavaFX के साथ सामान्य है?
 – 
Roy K.
16 पद 2020, 22:02
@रॉयके. मुझे लगता है हां। जावा इस तरह काम करता है... सभी वस्तुओं को संदर्भों के माध्यम से एक्सेस किया जाता है।
 – 
James_D
16 पद 2020, 22:04
@रॉयके. और हाँ, टूलकिट की परवाह किए बिना, किसी भी UI विकास में MVC आम है। यह एक डिज़ाइन पैटर्न है जो 1970 के दशक में वापस जाता है; इन दिनों (एमवीपी, एमवीवीएम) कई अलग-अलग विविधताएं हैं और इसे वेब अनुप्रयोगों में उपयोग के लिए भी अनुकूलित किया गया है (हालांकि यह अनुकूलन इसे बहुत अलग दिखता है)। देखें
 – 
James_D
16 पद 2020, 22:06