public class InventoryController {
private static final Logger LOGGER = Logger.getLogger(InventoryController.class.getName());
@FXML private FlowPane cardsContainer;
@FXML private TextField searchBarInventory;
@FXML private Button filterButton;
@FXML private Button exportButton;
@FXML private Button newProductBtn;
private final DatabaseConnection databaseConnection;
private MainViewController mainViewController;
public InventoryController() {
this.databaseConnection = new DatabaseConnection();
}
//Method to set the main view controller reference
public void setMainViewController(MainViewController mainViewController) {
this.mainViewController = mainViewController;
}
@FXML
public void initialize() {
cardsContainer.setHgap(10);
cardsContainer.setVgap(15);
// Bind flowpane width to parent scrollpane
javafx.application.Platform.runLater(() -> {
Parent current = cardsContainer.getParent();
while (current != null) {
if (current instanceof ScrollPane scrollPane) {
cardsContainer.prefWidthProperty().bind(scrollPane.widthProperty().subtract(30));
}
current = current.getParent();
}
});
loadInventoryItems();
setupNewProductButton();
}
private void loadInventoryItems() {
try {
cardsContainer.getChildren().clear();
databaseConnection.loadInventory().forEach(this::createInventoryCard);
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Failed to load inventory items", e);
showError("Failed to load inventory items: " + e.getMessage());
}
}
private void createInventoryCard(InventoryGS item) {
// Main card container
VBox card = new VBox();
card.getStyleClass().add("inventory-card");
card.setPrefWidth(Control.USE_COMPUTED_SIZE);
card.setPrefHeight(Control.USE_COMPUTED_SIZE);
card.setMaxWidth(Double.MAX_VALUE);
card.setMinHeight(120);
card.setOnMouseClicked(event -> showProductDetails(item));
// Content container
HBox content = new HBox(15);
content.setPadding(new Insets(10));
content.setAlignment(Pos.CENTER_LEFT);
content.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(content, Priority.ALWAYS);
// Product image
StackPane productImage = createProductImage(item);
// Main content area container
HBox mainContentArea = new HBox();
mainContentArea.setAlignment(Pos.CENTER_LEFT);
mainContentArea.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(mainContentArea, Priority.ALWAYS);
// Left side with name and specs - flexible width
VBox nameAndSpecs = new VBox(8);
nameAndSpecs.setAlignment(Pos.CENTER_LEFT);
HBox.setHgrow(nameAndSpecs, Priority.ALWAYS);
// Product Name
Label nameLabel = new Label(item.getItemName());
nameLabel.getStyleClass().add("card-title");
// Horizontal specifications layout
HBox specsContainer = new HBox(20);
specsContainer.setAlignment(Pos.CENTER_LEFT);
// Type label with grey color
Label typeValue = new Label(item.getItemType().getLabel());
typeValue.setTextFill(Color.GRAY);
typeValue.getStyleClass().add("specs-value");
// Size label
Label sizeValue = new Label("Size: " + item.getAmperes());
sizeValue.getStyleClass().add("specs-value");
// Office label
Label officeValue = new Label("Office: " + item.getOffice());
officeValue.getStyleClass().add("specs-value");
specsContainer.getChildren().addAll(typeValue, sizeValue, officeValue);
nameAndSpecs.getChildren().addAll(nameLabel, specsContainer);
// Right-side elements container with fixed layout
HBox rightSection = new HBox();
rightSection.setAlignment(Pos.CENTER_RIGHT);
// Price section - fixed width
VBox priceSection = new VBox();
priceSection.setPrefWidth(120); // Fixed width
priceSection.setMinWidth(120);
priceSection.setMaxWidth(120);
priceSection.setAlignment(Pos.CENTER);
// First separator
Separator priceSeparator = new Separator(Orientation.VERTICAL);
priceSeparator.setPrefHeight(60);
// Price container - centered within fixed width container
VBox priceContainer = new VBox(5);
priceContainer.setAlignment(Pos.CENTER);
Label priceLabel = new Label("Price");
priceLabel.getStyleClass().add("card-label");
Label priceValue = new Label("Ksh " + item.getPrice());
priceValue.getStyleClass().add("price-value");
priceContainer.getChildren().addAll(priceLabel, priceValue);
// Add price components to fixed width section
priceSection.getChildren().add(priceContainer);
HBox.setHgrow(priceSection, Priority.NEVER); // Prevent growing
// Stock section - fixed width
VBox stockSection = new VBox();
stockSection.setPrefWidth(100); // Fixed width
stockSection.setMinWidth(100);
stockSection.setMaxWidth(100);
stockSection.setAlignment(Pos.CENTER);
// Second separator
Separator stockSeparator = new Separator(Orientation.VERTICAL);
stockSeparator.setPrefHeight(60);
// Stock container - centered within fixed width container
VBox stockContainer = new VBox(5);
stockContainer.setAlignment(Pos.CENTER);
Label stockLabel = new Label("Stock");
stockLabel.getStyleClass().add("card-label");
Label stockValue = new Label(item.getStock());
stockValue.getStyleClass().add("stock-value");
stockContainer.getChildren().addAll(stockLabel, stockValue);
// Add stock components to fixed width section
stockSection.getChildren().add(stockContainer);
HBox.setHgrow(stockSection, Priority.NEVER); // Prevent growing
// Action buttons
HBox actions = createActionButtons(item);
HBox.setHgrow(actions, Priority.NEVER); // Prevent growing
// Add all elements to the right section in precise order
rightSection.getChildren().addAll(
priceSeparator,
priceSection,
stockSeparator,
stockSection,
actions
);
// Add left and right sections to main content area
mainContentArea.getChildren().addAll(nameAndSpecs, rightSection);
// Add image and main content area to content container
content.getChildren().addAll(productImage, mainContentArea);
card.getChildren().add(content);
// Set user data for identification (used in delete functionality)
card.setUserData(item.getItemName());
// Add to FlowPane
cardsContainer.getChildren().add(card);
// Make card take full width of FlowPane
card.prefWidthProperty().bind(cardsContainer.widthProperty().subtract(50));
}
private void showProductDetails(InventoryGS item) {
if (mainViewController != null) {
//Load the product details pane through the main controller
Object controller = mainViewController.showSlidingPanel("/com/example/ims/ProductDetails.fxml");
if (controller instanceof ProductDetailsController detailsController) {
detailsController.setInventoryController(this);
detailsController.setProductDetails(item);
}
}
else {
LOGGER.log(Level.SEVERE, "MainViewController reference is null, cannot show product details");
showError("System error: Cannot display product details");
}
}
private StackPane createProductImage(InventoryGS item) {
StackPane imageContainer = new StackPane();
imageContainer.setPrefSize(100, 100);
imageContainer.setMinSize(100, 100);
imageContainer.setMaxSize(100, 100);
imageContainer.getStyleClass().add("product-image-container");
ImageView imageView = new ImageView();
imageView.setFitWidth(95);
imageView.setFitHeight(95);
imageView.setPreserveRatio(true);
imageView.getStyleClass().add("product-image");
try {
Image image;
if (item.getImagePath() != null && !item.getImagePath().isEmpty()) {
if (item.getImagePath().startsWith("/")) {
//Use getResourceAsStream for resources in the classpath
image = loadImageSafely(item.getImagePath());
} else {
//Use file: protocol for external files
image = loadImageSafely("File:" + item.getImagePath());
}
} else {
image = loadImageSafely("/Images/imageunavailable.png");
}
//Only set the image if it was successfully loaded
if(image != null) {
imageView.setImage(image);
}
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to load product image" + item.getImagePath(), e);
Image defaultImage = loadImageSafely("/Image/imageunavailable.png");
if (defaultImage != null) {
imageView.setImage(defaultImage);
}
}
imageContainer.getChildren().add(imageView);
return imageContainer;
}
/**
* Safely load an image, handling exceptions and returning null if the image can't be loaded
*/
private Image loadImageSafely(String path) {
try{
if(path.startsWith("file:")){
return new Image(path);
}
else {
return new Image(Objects.requireNonNull(getClass().getResourceAsStream(path)));
}
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to load image: " + path, e);
return null;
}
}
private HBox createActionButtons(InventoryGS item) {
HBox actions = new HBox(10);
actions.setAlignment(Pos.CENTER_RIGHT);
Button deleteButton = new Button("Delete");
deleteButton.getStyleClass().add("delete-button");
deleteButton.setOnAction(e -> handleDelete(item));
actions.getChildren().addAll(deleteButton);
return actions;
}
private void handleDelete(InventoryGS item) {
Alert confirmDialog = new Alert(Alert.AlertType.CONFIRMATION);
confirmDialog.setTitle("Confirm Deletion");
confirmDialog.setHeaderText("Delete Item");
confirmDialog.setContentText("Are you sure you want to delete this item?");
confirmDialog.showAndWait().ifPresent(response -> {
if (response == ButtonType.OK) {
try {
if (databaseConnection.deleteInventoryItem(item)) {
cardsContainer.getChildren().removeIf(node ->
node.getUserData() != null &&
node.getUserData().equals(item.getItemName())
);
showSuccess("Item deleted successfully");
} else {
showError("Failed to delete item");
}
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Database error when deleting item", e);
showError("Database Error: " + e.getMessage());
}
}
});
}
private void setupNewProductButton() {
newProductBtn.setOnAction(event -> {
// Implement new product functionality
LOGGER.info("New product button clicked");
showNewProductPane();
});
}
private void showNewProductPane() {
if (mainViewController != null) {
mainViewController.showSlidingPanel("/com/example/ims/NewProductPane.fxml");
}
else {
LOGGER.log(Level.SEVERE, "MainViewController reference is null, cannot show new product pane");
showError("System Error: Cannot display new product form");
}
}
private void showError(String message) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setContentText(message);
alert.showAndWait();
}
private void showSuccess(String message) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Success");
alert.setContentText(message);
alert.showAndWait();
}
}
< /code>
Изображения хранятся в папке изображений, поэтому использование GetResource имеет смысл, но я также хочу, чтобы пользователи получали изображения с своих ПК. Я понятия не имею, что мне нужно изменить в коде, чтобы загрузить изображения. Кстати, весь пользовательский интерфейс не загружает причина ошибки изображения, а ошибка указывает на пустое пространство, но это откуда код ссылается на базу данных.
Подробнее здесь: https://stackoverflow.com/questions/794 ... lass-javaf
Вызвано: java.lang.illegalargumentException: невозможно принуждать 0 к классу javafx.scene.image.image. Я искренне dk в ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение