Java: access user Generated Code from Library - java

I am making a Library for my pupils to create a GUI easy in Java,
but if they press a button in the Interface it should run a method created by them.
Is there any way to do this?
I am not really into Java, but the curriculum wants me to:(

You can use reflection to run their class without requiring they implement an interface although you would still have to provide instructions to limit the argument types. This works only for methods with no arguments.
java.awt.EventQueue.invokeLater(() -> {
JFrame frm = new JFrame();
JPanel pnl = new JPanel();
frm.add(pnl);
pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
pnl.add(new JLabel("Class"));
JTextField classField = new JTextField();
pnl.add(classField);
pnl.add(new JLabel("Method"));
JTextField methodField = new JTextField();
pnl.add(methodField);
JTextArea area = new JTextArea();
area.setPreferredSize(new Dimension(300, 300));
JButton btn = new JButton("Run");
pnl.add(btn);
pnl.add(area);
System.setOut(new PrintStream(new OutputStream() {
#Override
public void write(int b) throws IOException {
area.append(new String(new byte[]{(byte) b}));
}
}));
btn.addActionListener(e -> {
try {
Class cls = Class.forName(classField.getText());
Method m = null;
Method ma[] = cls.getDeclaredMethods();
String methodName = methodField.getText().trim();
m = cls.getMethod(methodName,new Class[]{});
Object o = cls.newInstance();
Object mr = m.invoke(o);
if(null != mr) {
area.append("\nreturned "+mr.toString()+"\n");
}
} catch (Exception ex) {
ex.printStackTrace();
area.append("\nException "+ex.getMessage()+"\n");
}
});
frm.pack();
frm.setVisible(true);
});
given a class like:
public class StudentClass {
public void print10() {
int sum= 0;
for(int i = 0; i< 10; i++ ) {
System.out.println("i = "+i);
sum+=i;
}
}
}
The fields would be need to be filled with StudentClass and print10 and the compiled class needs to be on your classpath.
Perhaps a better option would be to teach Processing (https://processing.org/). This is essentially java since the Processing code gets pasted into a java class behind the scenes but is much more oriented to get beginners drawing graphical sketches. I guess you'd have to ask your administration if they would go for it and at some point the students would need to be able to write the code the processing tools are generating for them.

Related

Remove label before I click in java

ı have problem about delete a empty string values like we can see in picture,
in the first time if here is empty he give a error but after that even we write some strings in that blank,its still giving the same error how can ı delete this label before the sending again How can ı fix that problem ı tried some codes but nothing worked well please help about that
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
public class ui {
public static void main(String[] args) {
uiVision();
}
public static void uiVision() {
ImageIcon eyes = new ImageIcon("a.png");
Globals.jf.setTitle("Deneme Uygulamasi");
Globals.jf.setLocation(100,200);
JLabel label1,label2,label3;
Globals.jf.getContentPane().setLayout(new FlowLayout());
JTextField isim = new JTextField(20);
JTextField soyisim = new JTextField(20);
JTextField pasaport = new JTextField(20);
JTextField mail = new JTextField(20);
JPasswordField passwordField = new JPasswordField(10);
JPasswordField passwordField2 = new JPasswordField(10);
JButton buton1 = new JButton("Send");
JButton buton2 = new JButton(eyes);
JButton buton3 = new JButton(eyes);
JButton buton4 = new JButton("!");
label1 = new JLabel("Name:");// -8
label2 = new JLabel("Surname:");// -9
label3 = new JLabel("Passaport-ID:");//+ 10
JLabel label4 = new JLabel("Mail:");// +10
JLabel label5 = new JLabel("Password:");//+10
JLabel label6 = new JLabel("Re-Password:");// +20
buton1.setBounds(170,400,150,30);
buton2.setBounds(320,190,50,30);
buton3.setBounds(320,230,50,30);
buton4.setBounds(370,230,50,30);
isim.setBounds(170,30,150,30);
soyisim.setBounds(170,70,150,30);
pasaport.setBounds(170,110,150,30);
mail.setBounds(170,150,150,30);
passwordField.setBounds(170,190,150,30);
passwordField2.setBounds(170,230,150,30);
label1.setBounds(125,30,150,30);
label2.setBounds(106,70,150,30);
label3.setBounds(90,110,150,30);
label4.setBounds(132,150,150,30);
label5.setBounds(105,190,150,30);
label6.setBounds(91,230,150,30);
Globals.jf.add(buton1);Globals.jf.add(buton2);Globals.jf.add(buton3);
Globals.jf.add(label1);Globals.jf.add(label2);Globals.jf.add(label3);Globals.jf.add(label4); Globals.jf.add(label5);Globals.jf.add(label6);
Globals.jf.add(isim);Globals.jf.add(soyisim);Globals.jf.add(pasaport);Globals.jf.add(mail);Globals.jf.add(passwordField);Globals.jf.add(passwordField2);
Globals.jf.setSize(1000,500);
buton2.addActionListener(l -> {
if ( passwordField.getEchoChar() != '\u0000' ) {
passwordField.setEchoChar('\u0000');
} else {
passwordField.setEchoChar((Character) UIManager.get("PasswordField.echoChar"));
}
});
buton3.addActionListener(l -> {
if ( passwordField2.getEchoChar() != '\u0000' ) {
passwordField2.setEchoChar('\u0000');
} else {
passwordField2.setEchoChar((Character) UIManager.get("PasswordField.echoChar"));
}
});
buton1.addActionListener(e -> {
checkEmpty(isim.getText(),label1.getText(),label1);
checkEmpty(soyisim.getText(),label2.getText(),label2);
checkEmpty(pasaport.getText(),label3.getText(),label3);
checkEmpty(mail.getText(),label4.getText(),label4);
ExitWhenLoopEnd();
Globals.globalInt = 0;
System.out.println(passwordField.getPassword());
System.out.println(passwordField2.getPassword());
Globals.clickCount++;
});
Globals.jf.setLayout(null);
Globals.jf.setVisible(true);
Globals.jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void checkEmpty(String value,String label,JLabel labelname) {
Integer syc = Integer.valueOf(0);
if(value != null && !value.trim().isEmpty()) {
if(Globals.globalInt != 4) {
Globals.globalInt++;
}
syc = 1;
}
else {
CreateEmptyMessageError(label,labelname,Globals.jf);
syc = -1;
}
System.out.println(syc);
}
public static void CreateEmptyMessageError(String labelError,JLabel label,JFrame jf) {
Globals.labelx = new JLabel(labelError.split(":")[0]+" is empty!");
Globals.labelx.setBounds(label.getBounds().x+250,label.getBounds().y,label.getWidth(),label.getHeight());
Globals.labelx.setForeground(Color.RED);
jf.add(Globals.labelx);
jf.revalidate();
jf.repaint();
}
public class Globals {
public static int globalInt = 0;
public static JLabel labelx = null;
public static JFrame jf = new JFrame();
public static int clickCount = 0;
public static int lastVal = 0;
public static int syc = 0;
}
public static void ExitWhenLoopEnd() {
if(Globals.globalInt == 4) {
System.exit(0);
}
}
}
Your problem is that you're creating a new JLabel and adding it to the GUI each time CreateEmptyMessageError(...) is called, and by doing this, you have no reference to this object, and no way to change its state.
The solution is to not do this, to instead create the error message label when you create the GUI itself, assign it to an instance field, and in that method above to not create a new JLabel object but rather to set the text of the existing object, one that shows a warning if the JTextField is empty, and one that sets the JLabel text to the empty String, "", if the JTextField has text.
Also,
As Progman has suggested in comments, avoid the use of static fields and methods unless the use suggests that these should be used, and this isn't the case here. Instead, use private instance fields and methods. This will make your code easier to mock/test/extend and re-use, this reduces potential for hard to identify bugs by reducing your code's cyclomatic complexity and coupling.
Avoid the use of null layouts and setBounds(...) and instead learn and use the layout managers.
Learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
Give your fields names that describe what they represent, making your code self-commenting and easier to understand.

How can i access a linked list that is implement by me form outside of class

I have a linked list that store bunch of instrument as an object. And i want to access and display it on a GUI. What are some good ways to access it instead of just create a method and return the list to the GUI.
Pls gives some advice.
I will be appreciated.
It depends if you mean the class or an instance of your class. If you mean a class its just an import. If you need an instance of a class there are other ways like making it static (quick and dirty) or using a singleton if just one copy is allowed.
class InstrumentDisplayPanel extends JPanel implements ActionListener {
JPanel status = new JPanel();
JPanel action = new JPanel();
JLabel name = new JLabel();
JLabel number = new JLabel();
JButton next = new JButton("next");
JButton previous = new JButton("previous");
InstrumentDisplayPanel() {
this.setPreferredSize(new Dimension(200,200));
DoublyLinkedList<Instrument> instrumentList = FileRead.loadInstrument();
Node tempNode = instrumentList.getFirstItem();
Item tempItem = (Item)tempNode.getItem();
name.setText(tempItem.getName());
number.setText(tempItem.getNumber());
status.add(name);
status.add(number);
action.add(next);
action.add(previous);
add(status);
add(action);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == next) {
}
}
}
public static DoublyLinkedList<MusicSheet> loadMusicSheet(){
System.out.println("I am loading");
Scanner musicSheetInput = null;
try
{
musicSheetInput = new Scanner(new File("musicSheet.txt"));
}
catch(FileNotFoundException instrument)
{
System.out.println("File does Not Exist Please Try Again: ");
}
DoublyLinkedList<MusicSheet> musicSheetList = new DoublyLinkedList<MusicSheet>();
while (musicSheetInput.hasNextLine()){
String name = musicSheetInput.next();
String number = musicSheetInput.next();
String description = musicSheetInput.nextLine();
if(name.equals("GuitarSheet")){
musicSheetList.add(new GuitarSheet(name,number,description));
}
else if(name.equals("ViolinSheet")){
musicSheetList.add(new ViolinSheet(name,number,description));
}
else if(name.equals("CelloSheet")){
musicSheetList.add(new CelloSheet(name,number, description));
}
}
musicSheetList.display();
return musicSheetList;
}

Simple Calculator with all buttons created and actions added in JButton array

I'm self learning java beginner
i'm trying to create simple calculator using java swing and i want to create array of JButtons to create all the buttons in the project , i had some issues so i declare all variables outside the constructor
public class SimpleCalculator extends JFrame implements ActionListener {
JButton btnArray[] = new JButton[16];
JLabel nameLabel = new JLabel("Ghanayem's Calculator",
SwingConstants.CENTER);
JTextField txt = new JTextField();
JPanel numPanel = new JPanel(new GridLayout(4, 3, 15, 5));
JPanel opPanel = new JPanel(new GridLayout(4, 1, 0, 5));
JPanel panel = new JPanel(new GridLayout(2, 1, 0, 5));
int counter;
char operation;
double operand1;
double operand2;
like that ,and i think to add actions to buttons inside for-loop no compiler errors every thing is ok
for (counter = 0; counter < 10; counter++) {
btnArray[counter] = new JButton("" + counter);
btnArray[counter].addActionListener(this);
}
and here is action performed implementation
#Override
public void actionPerformed(ActionEvent e) {
txt.setText(txt.getText() + counter);
}
just like that ,when i try to run the program and press any number button the number added to text field is "16" for all buttons, and this is main method
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SimpleCalculator frame = new SimpleCalculator();
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
i am getting crazy i don't know what is wrong , please i need your help this my first swing application i am so disperate
thank you
Try something like this (I can't test right now so it may contain some lesser errors):
#Override
public void actionPerformed(ActionEvent e) {
String value = ((JButton)e.getSource()).getText();
Integer intValue = Integer.parseInt(value);
Integer intValue2 = Integer.parseInt(txt.getText());
txt.setText( "" + (intValue + intValue2));
}
#Override
public void actionPerformed(ActionEvent e) {
JButton b = (JButton) e.getSource();
txt.replaceSelection(b.getActionCommand());
}
this is a solution for my question i found here
java-action-listener
#Override
public void actionPerformed(ActionEvent e) {
String value = (JButton) e.getSource().getText();
txt.setText(txt.getText() + value);
}
and this is another solution #Paco Abato helps me to find

Setting text of JLabel within paint(g)- is this wrong?

Snippet of code is here:
int area;
int[] xcoords = new int[3];
xcoords[0] = coordsAX;
xcoords[1] = coordsBX;
xcoords[2] = coordsCX;
sortArray(xcoords);
int[] ycoords = new int[3];
ycoords[0] = coordsAY;
ycoords[1] = coordsBY;
ycoords[2] = coordsCY;
sortArray(ycoords);
//Remember, array[0] is the biggest and array[2] is the smallest!
int rectWidth = xcoords[0] - xcoords[2];
int rectHeight = ycoords[0] - ycoords[2];
area = (rectWidth * rectHeight);
System.out.println(area);
lblArea.setText("Area: " + area);
The entirety of the code is within the paint(g) method of my applet. I'm aiming to let the user be able to see the JLabel. Calculations go absolutely fine. But when I run, the applet looks like:
I've gathered that the setText line should not be in paint(g) but, in that case, where should it go in order to make it so the JLabel remains the same until a new triangle is generated (by clicking "Click Me" button)?
Please note that I'm a high schooler teaching myself Java and, as a result, my knowledge of the language looks like a hunk of Swiss Cheese. I'd appreciate explanations that don't explain too many topics that are well above the level of basic applet making. :)
Appreciate any help! Thanks!
Presumably you have an action listener attached to the "click me" button.
When the action is fired, I would update the label and the UI at that point.
You might like to have a read through How to Write an Action Listener
(I'm also kind of worried that it looks like you're using AWT instead of Swing, but I could be mistaken ;))
UPDATED example
public class TestArea {
public static void main(String[] args) {
new TestArea();
}
public TestArea() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AreaPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AreaPane extends JPanel {
private JLabel areaLabel;
public AreaPane() {
areaLabel = new JLabel("Area: ...");
JButton clickMe = new JButton("Click Me");
clickMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
areaLabel.setText("Area: " + NumberFormat.getNumberInstance().format(Math.random() * 1000));
// update UI as required
}
});
add(areaLabel);
add(clickMe);
}
}
}

return an ArrayList to swing with logger interface

I'm using the code in this answer to provide logging functionality, and it works well! Thanks gustafc.
Sending messages to a swing JTextArea from different places
I want to use this approach and add the function: writeEntry(String, String) to write to an ArrayList that I can hopefully access from swing; i.e, click 'show' and have it write this list of word pairs to a JText element.
so adding a bit to gustafc's code.
the interface:
package com.example.logging;
public interface SimpleActivityLogger {
void logAction(String message);
void writeEntry(String s1); //*** I added this ***
}
passing it to another class as per gustafc's example:
public class SimpleComponentLogger implements SimpleActivityLogger{
private JTextComponent target;
private ArrayList data;
public SimpleComponentLogger(JTextComponent target, ArrayList data){
this.target = target;
this.data = data;
}
public void logAction(final String message){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
target.setText(String.format("%s%s%n", new Object[]{target.getText(), message}));
}
});
}
public void writeEntry(String s1){
data.add(s1);
System.out.println("data array length: " + data.size());
}
}
and then making an implementation:
// this originally extended NotesThread,
// but I assume you won't have that on your system
public class LookupIterator3 extends Thread {
private SimpleActivityLogger logger;
// Constructor that passes logger instance
public LookupIterator3(SimpleActivityLogger logger){
this.logger = logger;
}
public void doLookup(){
this.start();
}
public void run() {
String[] words = {"the", "quick", "smart", "fox", "jumps", "over", "the", "lazy", "dog"};
for(int i=0; i<words.length; i++){
synchronized(words){
try{
logger.logAction(words[i]);
words.wait(500);
}
catch(InterruptedException ie){ie.printStackTrace();}
}
logger.writeEntry(words[i]);
}
}
}
however, when I try to access the ArrayList from swing, it comes back size()=0.
Here's a big chunk of swing, but you should be able to just copy and paste it:
public class MySwingTest extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField filename = new JTextField();
private JTextField dir = new JTextField();
private JTextPane output, answersPane;
private JScrollPane scroller;
private SimpleComponentLogger logger;
private ArrayList answer;
public MySwingTest() {
JMenu fileMenu;
JMenuBar menuBar;
JMenuItem menuOpen, menuExit;
JButton answerButton = new JButton("show answers");
answerButton.addActionListener(new MyListener());
menuBar = new JMenuBar();
fileMenu = new JMenu("File");
menuBar.add(fileMenu);
menuOpen = new JMenuItem("open file");
menuExit = new JMenuItem("exit");
answer = new ArrayList();
output = new JTextPane();
logger = new SimpleComponentLogger(output, answer);
scroller = new JScrollPane(output, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
output.setEditable(false);
answer = new ArrayList();
answersPane = new JTextPane();
answersPane.setSize(100, 200);
answersPane.setEditable(false);
fileMenu.add(menuOpen);
fileMenu.add(menuExit);
menuOpen.addActionListener(new MyListener());
menuExit.addActionListener(new MyListener());
JPanel p = new JPanel();
p.setLayout(new GridLayout(2, 1));
p.add(filename);
p.add(dir);
Container cp = getContentPane();
cp.add(menuBar,BorderLayout.NORTH);
cp.add(p);
cp.add(scroller, BorderLayout.CENTER);
cp.add(answersPane, BorderLayout.WEST);
cp.add(answerButton, BorderLayout.SOUTH);
dir.setEditable(false);
filename.setEditable(false);
}
// Inner class listener
class MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String eventCommand = e.getActionCommand();
if(eventCommand.equals("exit")){
System.exit(0);
}
if(eventCommand.equals("show answers")){
String entry = (String)answer.get(0);
answersPane.setText(entry);
}
else {
LookupIterator3 lu3 = new LookupIterator3(logger);
lu3.doLookup();
}
}
}
public static void main(String[] args) {
run(new MySwingTest(), 450, 600);
}
public static void run(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}
Sorry about the long question, but this is doing my head in!
Any suggestions?
(I know I'm going to get ragged for writing a long qn, but I don't know what I could have left out)
OK. long edit complete.
Open that baby up and select "open file" from the menu. It will run without a filechooser.
The problem is actually quite simple: in your MySwingTest constructor you have twice the line :
answer = new ArrayList();
once before you create your logger and once after. Simply drop the second call and it should work fine.
Note: it is really a bad practice to share ArrayList between your instances (responsability is spread over several classes). It would be a lot simpler if you only had your logger creating directly its own ArrayList and providing access to it with a getter. Even better, it could directly offer an access to the objects it contains (preventing the possibility for other instances to modify the content of the ArrayList).
Note 2: consider using interface-declaration over class-declaration: use List instead of ArrayList in order to reduce coupling.
Note 3: I would strongly encourage you tu type your collections: List<String> answer = new ArrayList<String>();

Categories