javafx 问题整理
记录一下javaFx的使用的问题
这些问题都是在开发rv64仿真工具中遇到的,下图是目前阶段的效果 https://github.com/anons-org/opencar/
Location is not set.
错误写法(或许是老版的写法,未验证)
FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/setings.fxml"));
换成
URL path = this.getClass().getClassLoader().getResource("fxml/main.fxml"); // 注意路径不带/开头
File file = new File(path.getFile());
root = FXMLLoader.load(file.toURI().toURL());
tableView
tv实现内存查看工具
- 如下
数据我用map去构造,每行数据一个map,每个map 16个key 分别是0~15 ,这些key对应tv表头的列即可,map的val存一个对象
该对象两个字段一个是原始值 一个是用于显示的值,因为数据需要格式化显示。
效果
相关代码
package com.far.vms.opencar.ui.main.RightTablePanle;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MemoryData {
/**
1 2 3......15
0x00000010 0e 0a 03......
0x00000020 0e 0a 03......
*/
Map<Long,List<Map<String,InnerMemVal>>> memMap = new HashMap<>();
public static class InnerMemVal{
int val;
String viewVal;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public String getViewVal() {
return viewVal;
}
public void setViewVal(String viewVal) {
this.viewVal = viewVal;
}
}
public Map<Long, List<Map<String, InnerMemVal>>> getMemMap() {
return memMap;
}
public void setMemMap(Map<Long, List<Map<String, InnerMemVal>>> memMap) {
this.memMap = memMap;
}
}
package com.far.vms.opencar.ui.main.RightTablePanle;
import cn.hutool.poi.excel.sax.SheetRidReader;
import javafx.beans.property.SimpleMapProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class TabMemoryInfo {
TabPane tabMemory;
TableView tvMemoryGrid;
ObservableList<Map<String, MemoryData.InnerMemVal>> tvMemoryGridDataWrapper = FXCollections.observableArrayList();
public TabPane getTabMemory() {
return tabMemory;
}
public void setTabMemory(TabPane tabMemory) {
this.tabMemory = tabMemory;
}
public TableView getTvMemoryGrid() {
return tvMemoryGrid;
}
public void setTvMemoryGrid(TableView tvMemoryGrid) {
this.tvMemoryGrid = tvMemoryGrid;
}
public void initControl() {
for (int i = 0; i < 15; i++) {
String colName = String.valueOf(i);
TableColumn<Map, String> tableColumn = new TableColumn<>(colName);
// new MapValueFactory<>(colName);
tableColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Map, String> mapStringCellDataFeatures) {
MemoryData.InnerMemVal xxx = (MemoryData.InnerMemVal) mapStringCellDataFeatures.getValue().get(tableColumn.getText());
ObservableValue<String> s = new SimpleStringProperty(xxx.getViewVal());
return s;
}
});
tvMemoryGrid.getColumns().add(tableColumn);
}
tvMemoryGrid.setItems(tvMemoryGridDataWrapper);
Map<String, MemoryData.InnerMemVal> innerMemValMap = new HashMap<>();
for (int i = 0; i < 15; i++) {
MemoryData.InnerMemVal memVal = new MemoryData.InnerMemVal();
memVal.setViewVal("xxx");
innerMemValMap.put(String.valueOf(i), memVal);
}
tvMemoryGridDataWrapper.add(innerMemValMap);
}
}
每个单元格增加鼠标右键菜单
- 这个是基于tableview添加菜单
https://blog.csdn.net/weixin_29629231/article/details/112525827
- 下面是基于每个单元格
package com.far.vms.opencar.ui.main.RightTablePanle;
import com.far.vms.opencar.OpenCarWindos;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.*;
import javafx.scene.layout.AnchorPane;
import javafx.util.Callback;
import java.util.List;
public class RightTablePanle {
private OpenCarWindos ctx;
TabPane rightTabPane;
//当前PC显示
TextField txtPcVal;
//通用寄存器
TableView tvGeneralRegister;
ObservableList<RegData> tvGeneralRegisterDataWrapper = FXCollections.observableArrayList();
public OpenCarWindos getCtx() {
return ctx;
}
public RightTablePanle setCtx(OpenCarWindos ctx) {
this.ctx = ctx;
return this;
}
public TabPane getRightTabPane() {
return rightTabPane;
}
public void setRightTabPane(TabPane rightTabPane) {
this.rightTabPane = rightTabPane;
}
public void initControl() {
SplitPane splitPane = (SplitPane) ctx.getRootMain().lookup("#spbox");//#ta是textarea的id号
var scrollPane = splitPane.getItems();
for (var e : scrollPane) {
if (e instanceof ScrollPane) {
ScrollPane scrollPane1 = ((ScrollPane) e);
rightTabPane = (TabPane) ((AnchorPane) scrollPane1.getContent()).lookup("#tabRightGroup");
rightTabPane.getTabs().forEach(item -> {
if ("tabItemRegInfo".equals(item.getId())) {
txtPcVal = (TextField) item.getContent().lookup("#txtPcVal");
tvGeneralRegister = (TableView) item.getContent().lookup("#tvGeneralRegister");
}
});
}
}
initGeneralRegisterTv();
}
public void initGeneralRegisterTv() {
//创建表格的列
TableColumn regName = new TableColumn<>("寄存器");
TableColumn viewAddr = new TableColumn<>("地址");
TableColumn viewVal = new TableColumn<>("值");
viewAddr.setCellFactory(new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn tableColumn) {
final TableCell<RegData, String> cell = new TableCell<>();
//javafx的api非常奇怪,这行代码的作用是 将新的cell的值 和新的cell的值进行绑定
//简单说 必须有这句,才会把值显示出来
cell.textProperty().bind(cell.itemProperty());
// cell.setOnKeyPressed(new EventHandler<KeyEvent>() {
// @Override
// public void handle(KeyEvent keyEvent) {
//
// if (keyEvent.getCode() == KeyCode.C) {
// // final Clipboard clipboard = Clipboard.getSystemClipboard();
// final ClipboardContent content = new ClipboardContent();
// content.putString(cell.getItem());
// }
// }
// });
cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
//获取选中单元格的值
var itemval = cell.getItem();
RegData regData = cell.getTableRow().getItem();
int xx = 1;
//设置菜单
//https://blog.csdn.net/qq_26486347/article/details/96600969
ContextMenu contextMenu = new ContextMenu();
// 菜单项
MenuItem hex = new MenuItem("十六进制");
hex.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue("0x" + Long.toHexString(regData.getAddr()));
}
});
MenuItem bin = new MenuItem("二进制");
bin.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue("0b" + Long.toBinaryString(regData.getAddr()));
}
});
MenuItem orc = new MenuItem("十进制");
orc.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue(String.valueOf(regData.getAddr()));
}
});
contextMenu.getItems().addAll(hex, bin, orc);
cell.setContextMenu(contextMenu);
}
}
});
return cell;
}
});
viewVal.setCellFactory(new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn tableColumn) {
final TableCell<RegData, String> cell = new TableCell<>();
//javafx的api非常奇怪,这行代码的作用是 将新的cell的值 和新的cell的值进行绑定
//简单说 必须有这句,才会把值显示出来
cell.textProperty().bind(cell.itemProperty());
cell.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
//获取选中单元格的值
var itemval = cell.getItem();
RegData regData = cell.getTableRow().getItem();
int xx = 1;
//设置菜单
//https://blog.csdn.net/qq_26486347/article/details/96600969
ContextMenu contextMenu = new ContextMenu();
// 菜单项
MenuItem hex = new MenuItem("十六进制");
hex.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue(regData.toHexStr());
}
});
MenuItem bin = new MenuItem("二进制");
bin.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue(regData.toBinStr());
}
});
MenuItem orc = new MenuItem("十进制");
orc.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
cell.itemProperty().setValue(String.valueOf(regData.getVal()));
}
});
contextMenu.getItems().addAll(hex, bin, orc);
cell.setContextMenu(contextMenu);
}
}
});
return cell;
}
});
//将表格的列和类的属性进行绑定
regName.setCellValueFactory(new PropertyValueFactory<>("regName"));
viewAddr.setCellValueFactory(new PropertyValueFactory<>("viewAddr"));
viewVal.setCellValueFactory(new PropertyValueFactory<>("viewVal"));
//添加到tableview
tvGeneralRegister.getColumns().addAll(regName, viewAddr, viewVal);
tvGeneralRegister.setItems(tvGeneralRegisterDataWrapper);
}
public void addDataToGeneralRegisterTv(List<RegData> regData) {
tvGeneralRegisterDataWrapper.clear();
regData.forEach(e -> {
tvGeneralRegisterDataWrapper.add(e);
});
}
public void setPcval(String pc) {
txtPcVal.setText(pc);
}
}
增加行点击事件,可拿到每列的数据然后做处理
这个行点击事件的clickCount总数 没有找到办法清零,导致点击数只增不减少,可以采取求模的办法判断点击次数,有知道解决办法的大佬们看到指点一下!
tv.setRowFactory(tview -> {
TableRow<CodeData> row = new TableRow<>();
row.setOnMouseClicked(event -> {
System.out.println(event.getClickCount() % 2 + "次");
// 点击两次 且 row不为空
if (event.getClickCount() % 1 == 0 && (!row.isEmpty())) {
CodeData rowData = row.getItem();
if (rowData.getCircle().isVisible()) {
rowData.getCircle().setVisible(false);
} else {
rowData.getCircle().setVisible(true);
}
}
});
return row;
});
连续点击某行无效,换行点击才有效的事件
// tv.getSelectionModel().getSelectedCells().addListener(new InvalidationListener() {
// @Override
// public void invalidated(Observable observable) {
// ObservableList<TablePosition> tbs = (ObservableList<TablePosition>) observable;
// tbs.forEach(e -> {
// System.out.println("多少次");
// if (e.getColumn() == 0) {
// Circle data = (Circle) e.getTableColumn().getCellData(e.getRow());
// if (data.isVisible()) {
// data.setVisible(false);
// } else {
// data.setVisible(true);
// }
// }
// });
//
// }
// });
快捷键 javafx
Ctrl+C
KeyCombination ctrl_c = new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_DOWN);
window.getScene().getAccelerators().put(ctrl_c, () -> {
System.out.println("快捷键CTRL + C");
System.out.println(Thread.currentThread().getName());
});
监听快捷键 javafx
window.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
//System.out.println("KeyEvent = " + e);
if (ctrl_c.match(e)) {
System.out.println("快捷键CTRL + C");
System.out.println(Thread.currentThread().getName());
}
});
生成jar问题
-
java.lang.NoClassDefFoundError:javafx/application/Application
-
开发时用的java17 但是生成javafx的jar包各种问题,无奈降到java11 但javafx 8之后就被移出jdk了。需要单独下载javafx的sdk包
我开发时javafx的sdk的api用的是17的,但运行jar时sdk用的是16,所以会看到下面的警告信息。。
javafxsdk下载
过期请联系我
链接:https://pan.baidu.com/s/1fES9WodOAtvFuS-2ErM__g?pwd=3v9l
提取码:3v9l
下载了sdk需要jar启动的时候指定位置
./java --module-path D:\AAAA_WORK\java\openjfx\openjfx-16_windows-x64_bin-sdk\javafx-sdk-16\lib --add-modules javafx.controls,javafx.fxml -jar E:\AAAA_CODE\new-eclipse-workspace\to-github\opencar\target\opencar-0.0.1-SNAPSHOT.jar
./java --module-path D:\AAAA_WORK\java\openjfx\openjfx-16_windows-x64_bin-sdk\javafx-sdk-16\lib --add-modules javafx.controls,javafx.fxml -jar E:\AAAA_CODE\new-eclipse-workspace\to-github\opencar\target\opencar-0.0.1-SNAPSHOT.jar
11月 30, 2022 11:33:02 上午 javafx.fxml.FXMLLoader$ValueElement processValue
警告: Loading FXML document with JavaFX API of version 17 by JavaFX runtime of version 16
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.far.demo</groupId>
<artifactId>opencar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>opencar</name>
<description>opencar</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>[2.0.0,3.0.0)</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>17.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>17.0.1</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<!--resources下一级的所有.xml .properties文件复制到config目录下-->
<targetPath>${project.build.directory}/config</targetPath>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<useUniqueVersions>false</useUniqueVersions>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.far.vms.opencar.Run</mainClass> <!-- 此处为主入口-->
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.8.3</version>
<configuration>
<mainClass>com.liumiaocn.javademo.Main</mainClass>
</configuration>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.openjfx</groupId>-->
<!-- <artifactId>javafx-maven-plugin</artifactId>-->
<!-- <version>0.0.8</version>-->
<!-- -->
<!-- <configuration>-->
<!-- <mainClass>com.far.vms.opencar.Run</mainClass>-->
<!-- </configuration>-->
<!-- </plugin>-->
</plugins>
</build>
</project>
本节参考
https://www.jianshu.com/p/51f818878eda
https://blog.csdn.net/qq_34444097/article/details/126556823
https://blog.csdn.net/weixin_44480167/article/details/120361097
结尾
javafx坑参考
https://zhuanlan.zhihu.com/p/30386925
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。