I'm using CookSwing (http://cookxml.yuanheng.org/cookswing/) to build a Java Swing UI, but the site doesn't have a lot of information. I'm stuck trying to get my Java class to retrieve the string from a textfield in the form (declared in XML). This should be easy to do, but nothing I've tried works. Does anyone have experience doing this? Here is the Java class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import cookxml.cookswing.CookSwing;
public final class CookSwingForm
{
// Listener for the Quit button
public ActionListener exitAction = new ActionListener()
{
public void actionPerformed (ActionEvent e)
{
System.exit(0);
}
};
public CookSwingForm()
{
CookSwing cookSwing = new CookSwing(this);
cookSwing.render("sampleform.xml").setVisible(true);
}
public static void main(String[] args)
{
new CookSwingForm();
}
}
Here is the XML file ("sampleform.xml"):
<frame title="Sample Form" size="300,70"
defaultcloseoperation="EXIT_ON_CLOSE">
<borderlayout>
<constraint location="West">
<textfield columns="20" />
</constraint>
<constraint location="East">
<button text="Quit" actionlistener="exitAction" />
</constraint>
</borderlayout>
</frame>
I just need to have the Java class retrieve the string from the textfield that's declared in the XML file. Any help is greatly appreciated. Thanks!
I think you should use the id attribute and then use that as the variable name for the text field.
The xml would look as : <textfield id="box1" />
Here is what you have to do:
JTextField txtField = (JTextField) cookSwing.getId("box1").object;
//now,set some text
txtField.setText("Blah!");
//or get some text as you may wish
Also. Looks like the library is no longer being developed. That's a red flag right there.
Related
I'm making a web file browser using ZK Components and find a block. Is there any way to update the ListBox model using the selected item of the listbox?
The use case is when traversing the files and folder, the user click the folder, and the list is refreshed with the content of the selected folder. The selection event is triggered and for regular file, it handle well, but not the folder.
My Code:
myfilesvm.zul
<zk>
<window apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('com.my.zk.mvvm.MyFilesViewModel')">
<hlayout>
<listbox vflex="true" hflex="1" model="#load(vm.files)"
id="fileBrowser" selectedItem="#bind(vm.selectedFile)">
<auxhead>
<auxheader colspan="3">File List</auxheader>
<auxheader colspan="3">
<hlayout>
<!-- breadcrumb, implemented later -->
</hlayout>
</auxheader>
</auxhead>
<listhead>
<listheader label="Name" />
<listheader label="Size" />
<listheader label="Modified" />
</listhead>
<template name="model" var="file">
<listitem>
<listcell label="#load(file.name)" />
<listcell label="#load(file.length())" />
<listcell label="#load(file.lastModified())" />
</listitem>
</template>
</listbox>
</hlayout>
<separator />
</window>
</zk>
MyFilesViewModel.java
package com.my.zk.mvvm;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zul.Filedownload;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import com.my.zk.FileCrumbManager;
public class MyFilesViewModel {
private static Logger log = LoggerFactory.getLogger(MyFilesViewModel.class);
// AuthenticationService authService = new AuthenticationServiceImpl();
// UserCredential cre = authService.getUserCredential();
String homeFolder = "D:\\path\\home";
ListModel<File> files = new ListModelList<File>(Arrays.asList(FileCrumbManager.populateList(new File(homeFolder))));
File selectedFile;
#Init
public void init() { // Initialize
}
public ListModel<File> getFiles() {
return files;
}
#NotifyChange({ "selectedFile" })
public void setFiles(ListModel<File> files) {
this.files = files;
}
public File getSelectedFile() {
return selectedFile;
}
public void pilihFile() {
if (getSelectedFile().isDirectory()) {
log.info("File is a directory");
this.files = new ListModelList<File>(
Arrays.asList(FileCrumbManager.populateList(new File(getSelectedFile().getAbsolutePath()))));
} else {
try {
Filedownload.save(getSelectedFile(), null);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
log.error(e.getMessage());
}
}
}
public void setSelectedFile(File selectedFile) {
this.selectedFile = selectedFile;
pilihFile();
}
}
Appreciate for any help. Thank you.
The correct way to refresh ListModelList in pilihFile() is:
this.files.clear();
this.files.addAll(Arrays.asList(FileCrumbManager.populateList(new File(getSelectedFile().getAbsolutePath()))));
Because Listbox is model-driven rendering, you should control the rendering by manipulating the model object. When you call methods of ListModelList, it will notify Listbox to render into a browser. If you replace this.files with a new object, ZK doesn't know it. That's why your browser doesn't have the update.
So basically I began a dummy JavaFX project just to achieve a minimalistic example for my actual problem. But now I am not even able to run that minimalistic project anymore and do not receive enough error information to actually google it myself out. So right now, when I run the code, I receive the given error stack, which does not lead me anywhere.
I am using IntelliJ. JavaFX libraries are set correctly and VM Options set to:
--module-path "C:\Program Files\Java\javafx-sdk-11.0.2\lib" --add-modules javafx.controls,javafx.fxml
On top, when I run the code, those errors pop up in console, but the application seems to still be running, because I need to press the Red Stop Button of IntelliJ to actually stop it.
Has anyone some guess, what goes wrong here? I am not experienced enough to follow those errors, since they do not point into my code, but rather into some Deep Java code.
The Exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.NullPointerException
at java.base/java.lang.reflect.Method.invoke(Method.java:559)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
... 5 more
Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
private Stage rootStage;
public BorderPane mainWindow;
public AnchorPane left;
public AnchorPane bottom;
#Override
public void start(Stage primaryStage) throws Exception {
this.rootStage = primaryStage;
loadMainWindow();
}
public void loadMainWindow() throws IOException {
FXMLLoader loaderMainWindow = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
mainWindow = loaderMainWindow.load();
FXMLLoader loaderLeft = new FXMLLoader(Main.class.getResource("Left.fxml"));
left = loaderLeft.load();
mainWindow.setLeft(left);
//mainWindow.setBottom(bottom);
Scene scene = new Scene(mainWindow);
rootStage.setScene(scene);
rootStage.show();
}
public void main(String[] args) {
launch(args);
}
}
MainWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainWindowController" />
MainWindowController:
package sample;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindowController implements Initializable {
private Main main;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void setMain(Main main) {
this.main = main;
}
}
Left.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LeftController">
<children>
<Button fx:id="button" layoutX="237.0" layoutY="169.0" mnemonicParsing="false" onAction="#buttonClick" text="Button" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
</children>
</AnchorPane>
LeftController.java:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.ResourceBundle;
public class LeftController implements Initializable {
#FXML
private Button button;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void buttonClick(javafx.event.ActionEvent actionEvent) {
System.out.println("Some Stuff");
}
}
Solution
The error you're getting is caused by your main(String[]) method not being static. If you make it static then the error will go away.
Some Explanation
JavaFX offers the ability to launch applications without providing a main method, so long as the main class is a subclass of Application. However, developers can still include a main method which means this special launch functionality has to handle that situation gracefully. In other words, an explicit main method present in the Application subclass must act like the entry point of the application from the developer's point of view. Nonetheless, behind the scenes some deep internal class has become the "real" main class.
To do this, the main method is located—if present at all—via Class#getMethod(String,Class...) which, while only returning public methods, doesn't distinguish between static and non-static methods. If found, Method#invoke(Object,Object...) is used to invoke the main method reflectively. The first argument of invoke is the instance that the method should be invoked on; in the case of static methods the value is null. Unfortunately, the code assumes the method it found is static which causes a NullPointerException to be thrown—you can't call an instance method on a null "instance".
Update: This issue has been submitted on GitHub (#570) and subsequently JBS (JDK-8230119). The current idea is to emit a warning rather than throw the NullPointerException. However, the functionality that allows launching without a main method may be deprecated in a future release, which will affect how this issue is addressed.
I have the setup below for the connection SQL Server with Java. Am also using javafx. I am very new to developing with Java. Note: I added the sqljdbc driver. I don't want to add main to DBConnection because am using the Connection method in the controller. Is there a way to fix this or how can I add main method without changing the connection method? Am getting error message:
Error Message
Error: Main method not found in class application.ConnectionDB, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:controller="application.MainController" prefHeight="407.0" prefWidth="578.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label layoutX="123.0" layoutY="65.0" prefHeight="31.0" prefWidth="79.0" text="Date:" />
<Label layoutX="123.0" layoutY="138.0" prefHeight="25.0" prefWidth="127.0" text="Rim Current Value:" />
<Label layoutX="125.0" layoutY="210.0" text="Rim Sales Value for the Month:" />
<Label layoutX="123.0" layoutY="283.0" text="Rim Sold Cost Bought:" />
<TextField fx:id="txtdate" layoutX="123.0" layoutY="97.0" />
<TextField fx:id="txtcurvalue" layoutX="123.0" layoutY="163.0" />
<TextField fx:id="txtsalesvalue" layoutX="123.0" layoutY="234.0" />
<TextField fx:id="txtsoldcost" layoutX="123.0" layoutY="300.0" />
<Button layoutX="246.0" layoutY="340.0" mnemonicParsing="false" onAction="#Rmsubmit" prefHeight="25.0" prefWidth="103.0" text="Submit" />
</children>
</AnchorPane>
Connection Class
package application;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ConnectionDB
{
public static Connection dbConn() {
Connection conn = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver:[server name];database=SalesManager;user=[username];password=[password];encrypt=true;trustServerCert ificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30";
conn = DriverManager.getConnection(url);
}
catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(ConnectionDB.class.getName()).log(Level.SEVERE,null,ex);
}
return conn;
}
}
Controller
package application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javax.print.DocFlavor.URL;
public class MainController {
#FXML
public TextField txtdate;
#FXML
public TextField txtcurvalue;
#FXML
public TextField txtsalesvalue;
#FXML
public TextField txtsoldcost;
public Connection conn =null;
public PreparedStatement pat = null;
#FXML
public void Rmsubmit(ActionEvent actionEvent) {
String sqla = "Insert into RimCalc(Date, Rim_Vale,Rim_Sales,Rim_Cost) Values (?,?,?,?)";
String date = txtdate.getText();
String rim_value = txtcurvalue.getText();
String Rim_Sales = txtsalesvalue.getText();
String rim_cost = txtsoldcost.getText();
try {
pat = conn.prepareStatement(sqla);
pat.setString(1, date);
pat.setString(2, rim_value);
pat.setString(3, Rim_Sales);
pat.setString(4, rim_cost);
int i = pat.executeUpdate();
if(i==1) {
System.out.println("Insert Successfully");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initializer(URL url, ResourceBundle rb) {
conn = application.ConnectionDB.dbConn();
}
}
Java programs require a main method as an entry point in order to run. The standard definition of a main method is like this:
public static void main(String[] args) {
// First code of your program goes here
}
This main() method should include the code that starts your application and loads any interface elements for display.
A JavaFX application also needs to have a class that extends Application and override its start() method.
Here is a very quick and dirty example of one such class:
import javafx.application.Application;
import javafx.stage.Stage;
class Main extends Application {
public static void main(String[] args) {
launch(args); // Starts the JavaFX application and calls the start() method
}
#Override
public void start(Stage primaryStage) throws Exception {
// Here is where you'll initialize your views and such
}
}
I would recommend taking a few Java and JavaFX tutorials to get a feel for some of the basics before attempting more complicated tasks like connecting to databases.
I make a simple JavaFX application. In this application there is a treetable with 2 columns and a check box. If check box is selected column 2 will be visible, otherwise not visible. To do this I bound tree table column visible property to checkbox selected property. When I click the check box column state change but at the same time gives.
Caused by: java.lang.RuntimeException: TreeTableColumn.visible : A
bound value cannot be set.
If I use bidirectional binding I don't get this error. But I don't need bidirectional binding. Is it a bug or I don't use bind correctly? Please use below code to reproduce this error. I use jdk1.8.0_111.
JavaFXApplication.java
package test;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXMLDocumentController.java
package test;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
public class FXMLDocumentController implements Initializable {
#FXML
private TreeTableView<?> table;
#FXML
private CheckBox box;
#FXML
private TreeTableColumn<?, ?> c2;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
c2.visibleProperty().bind(box.selectedProperty());
}
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.TreeTableColumn?>
<?import javafx.scene.control.TreeTableView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="390.0" prefWidth="452.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65" fx:controller="javafxapplication2.FXMLDocumentController">
<children>
<TreeTableView fx:id="table" layoutX="2.0" prefHeight="390.0" prefWidth="149.0">
<columns>
<TreeTableColumn prefWidth="75.0" text="C1" />
<TreeTableColumn fx:id="c2" prefWidth="75.0" text="C2" visible="false" />
</columns>
</TreeTableView>
<CheckBox fx:id="box" layoutX="234.0" layoutY="77.0" mnemonicParsing="false" text="CheckBox" />
</children>
</AnchorPane>
I think this actually is not a bug. It's definitely mysterious and unexpected behavior though. Part of the problem is that the binding conflict is coming from TableHeaderRow, which is created by the skin at display time.
The TableHeaderRow is responsible for rendering all the column headers, and it includes this built-in button for a menu that, by default, is a radio selection list of columns to show/hide:
As a result, the TableHeaderRow creates a bidirectional binding between these menu entries' selection state and each column's visible property.
It actually is possible to undo this binding but I found it annoying since the TableHeaderRow is null until the TableView is displayed. But, adapting this solution to access the TableHeaderRow, we can do something like:
TableHeaderRow headerRow = ((TableViewSkinBase) tableView.getSkin()).getTableHeaderRow();
try {
// get columnPopupMenu field
Field privateContextMenuField = TableHeaderRow.class.getDeclaredField("columnPopupMenu");
// make field public
privateContextMenuField.setAccessible(true);
// get context menu
ContextMenu contextMenu = (ContextMenu) privateContextMenuField.get(headerRow);
for (MenuItem menuItem : contextMenu.getItems()) {
// Assuming these will be CheckMenuItems in the default implementation
BooleanProperty selectedProperty = ((CheckMenuItem) menuItem).selectedProperty();
// In theory these menu items are in parallel with the columns, but I just brute forced it to test
for (TableColumn<?, ?> tableColumn : tableView.getColumns()) {
// Unlink the column's visibility with the menu item
tableColumn.visibleProperty().unbindBidirectional(selectedProperty);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
// Not strictly necessary but we don't want to be misleading :-p
tableView.setTableMenuButtonVisible(false);
But here's the kicker: you have to do this every time a column's visibility changes, because the TableHeaderRow has a listener that rebuilds the menu, and re-links the properties, every time a column is shown.
You could, of course, find a way to disable that listener.. but clearly this is already ridiculous and probably unnecessary.
Anyway, as you noted:
If I use bidirectional binding I don't get this error. But I don't need bidirectional binding.
I think the second statement isn't technically true: your use case doesn't require bidirectional binding, but it is actually appropriate here since there are other properties already linked with a column's visibility.
So, I would use bidirectional binding.
I am trying to create multiple file upload by using multiple af:inputFile component. Here is my xhtml:
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<f:view>
<af:document id="d1" title="Home">
<af:form id="f1" usesUpload="true">
<af:commandButton text="Add" immediate="true"
actionListener="#{viewScope.massUpload.add}"
id="cb2"/>
<af:panelGroupLayout layout="vertical" id="pgl1" partialTriggers="cb1">
<af:iterator value="#{viewScope.massUpload.fileComponents}" var="fileComponent"
id="i1" varStatus="status">
<af:inputFile binding="#{fileComponent}" id="if1"
value="#{viewScope.massUpload.files[status.index]}"/>
</af:iterator>
<af:commandButton text="Upload"
actionListener="#{viewScope.massUpload.upload}"
id="cb1"/>
</af:panelGroupLayout>
</af:form>
</af:document>
</f:view>
</jsp:root>
and this is the managed bean:
package com.edfx.massupload.bean;
import java.util.ArrayList;
import java.util.List;
import javax.faces.event.ActionEvent;
import oracle.adf.view.rich.component.rich.input.RichInputFile;
import oracle.stellent.ridc.IdcClientException;
import org.apache.myfaces.trinidad.model.UploadedFile;
public class MassUploadBean {
private List<RichInputFile> fileComponents = new ArrayList<RichInputFile>();
private List<UploadedFile> files = new ArrayList<UploadedFile>();
public MassUploadBean() {
super();
}
public void add(ActionEvent event) {
fileComponents.add(new RichInputFile());
files.add(null);
}
public void upload(ActionEvent event) throws IdcClientException {
for(UploadedFile file : files) {
System.out.println(file.getFilename());
}
}
public void setFiles(List<UploadedFile> files) {
this.files = files;
}
public List<UploadedFile> getFiles() {
return files;
}
public void setFileComponents(List<RichInputFile> fileComponents) {
this.fileComponents = fileComponents;
}
public List<RichInputFile> getFileComponents() {
return fileComponents;
}
}
The problems that I am facing are:
I have clicked on the Add button; a new file upload component added to the page; I browse a file; Again clicked on the Add button; Another file upload component added and the first file upload get submitted (but it is having a border, or something similar); I browse file from the second file upload; Again click on Add button; now the first file upload get cleared (reset) and the second file upload get submitted;
Whenever I clicked on the Add button the file get uploaded. Why? How to resist it? I have tried by setting atoSubmit="false" but no luck. Also tried to put the iterator, file uploader and the Upload button inside af:subForm
My requirement is to Upload the file when the upload button is clicked, not before.
Am I doing something wrong? Any pointer would be very helpful.
I see you're using IdcClientException which tells me you're uploading into UCM. If you're also using WebCenter then you might be able to use the out of the box Upload task flow that comes with WebCenter Portal: http://docs.oracle.com/cd/E29597_01/webcenter.1111/e25595/jpsdg_content_jsfpg.htm#autoId18
As of PS5 that task flow will do multifile upload for you.
THe later versions of ADF should help with bulk upload:
http://jdevadf.oracle.com/adf-richclient-demo/docs/tagdoc/af_inputFile.html
Turn on displayMode and maximumFiles (see also uploadType).