

Sistema de ServiçosJavaFX
Classe Java Configurações
Classe FabricaDeConexao
A classe FabricaDeConexao
é responsável pela criação e gerenciamento de um pool de conexões com o banco de dados, usando a biblioteca HikariCP
. Ela também fornece métodos para obter conexões do pool e para fechá-lo adequadamente quando não for mais necessário. Aqui está uma explicação detalhada do código:
1. Dependências e Configuração Inicial
A classe importa bibliotecas relevantes, incluindo HikariCP
, que é usada para gerenciamento de conexões, e SLF4J
para o log.
HikariConfig
: Classe que permite configurar o pool de conexões.HikariDataSource
: Gerencia o pool de conexões com base nas configurações definidas.Logger
eLoggerFactory
: Usados para registrar informações no log.
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.SQLException;
2. Definindo o Pool de Conexões
A variável estática dataSource
é usada para armazenar uma instância de HikariDataSource
, que será o pool de conexões.
O bloco static
é responsável por inicializar as configurações do pool de conexões assim que a classe é carregada na memória. Isso evita que a configuração precise ser feita repetidamente toda vez que uma conexão for solicitada.
setJdbcUrl
: Especifica a URL do banco de dados. No exemplo, a conexão é feita com um banco MySQL local chamadosistema_servico
.setUsername
esetPassword
: Credenciais usadas para conectar ao banco.setMaximumPoolSize
: Define o número máximo de conexões simultâneas no pool.setMinimumIdle
: Define o número mínimo de conexões que devem estar ociosas, mas prontas para uso imediato.setIdleTimeout
: Define o tempo em milissegundos antes de uma conexão ociosa ser fechada.setMaxLifetime
: Define o tempo máximo de vida de uma conexão antes que ela seja renovada.
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/sistema_servico");
config.setUsername("root");
config.setPassword("");
config.setMaximumPoolSize(10); // Máximo de conexões simultâneas no pool
config.setMinimumIdle(2); // Mínimo de conexões ociosas que o pool deve manter
config.setIdleTimeout(30000); // Tempo ocioso antes de fechar uma conexão
config.setMaxLifetime(1800000); // Tempo máximo de vida de uma conexão no pool
dataSource = new HikariDataSource(config); // Instancia o pool com base na configuração
}
3. Obtendo Conexões do Pool
O método obterConexao
retorna uma conexão ativa do pool. Ele utiliza o log para indicar que a conexão está sendo obtida.
Este método é chamado sempre que uma operação no banco de dados precisa ser realizada. Ele garante que as conexões são gerenciadas pelo pool, o que melhora o desempenho e evita que conexões sejam abertas e fechadas desnecessariamente.
public static Connection obterConexao() throws SQLException {
logger.info("Obtendo conexão do pool...");
return dataSource.getConnection();
}
4. Fechando o Pool de Conexões
O método fecharDataSource
é responsável por encerrar o pool de conexões. Esse método deve ser chamado quando a aplicação estiver sendo finalizada, para liberar todos os recursos.
Aqui, o pool é fechado e todas as conexões ativas são encerradas de forma limpa.
public static void fecharDataSource() {
if (dataSource != null) {
logger.info("Fechando o pool de conexões...");
dataSource.close();
}
}
Código Completo
package br.com.professorclaytonandrade.sistemaservicojavafx.config.conexao;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.SQLException;
public class FabricaDeConexao {
private static HikariDataSource dataSource;
private static final Logger logger = LoggerFactory.getLogger(FabricaDeConexao.class);
// Configuração do pool de conexões
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/sistema_servico");
config.setUsername("root");
config.setPassword("");
config.setMaximumPoolSize(10); // Máximo de conexões simultâneas
config.setMinimumIdle(2); // Número mínimo de conexões ociosas
config.setIdleTimeout(30000); // Tempo ocioso antes de fechar uma conexão
config.setMaxLifetime(1800000); // Tempo máximo de vida para cada conexão
dataSource = new HikariDataSource(config);
}
// Método para obter uma conexão
public static Connection obterConexao() throws SQLException {
logger.info("Obtendo conexão do pool...");
return dataSource.getConnection();
}
// Método para fechar o pool de conexões
public static void fecharDataSource() {
if (dataSource != null) {
logger.info("Fechando o pool de conexões...");
dataSource.close();
}
}
public static void main(String[] args) {
try (Connection conexao = FabricaDeConexao.obterConexao()) {
// Lógica para manipulação do banco de dados usando 'conexao'
logger.info("Conexão obtida com sucesso!");
} catch (SQLException e) {
logger.error("Erro ao obter a conexão: {}", e.getMessage());
}
}
}
6. Dependências no pom.xml
Adicione as seguintes dependências ao seu arquivo pom.xml
para incluir HikariCP
(pool de conexões), SLF4J
(para logging), e o driver JDBC para MySQL (ou outro banco de dados que você esteja utilizando):
<dependencies>
<!-- HikariCP (pool de conexões) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- SLF4J (logging) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
<!-- Driver JDBC do MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.34</version>
</dependency>
<!-- Adicione outras dependências aqui, se necessário -->
</dependencies>
7. Configuração do Módulo
Se você estiver utilizando um projeto modular (com module-info.java
), você precisará declarar os módulos necessários. Aqui está um exemplo de como o module-info.java
poderia ser configurado para incluir HikariCP
, SLF4J
, e o driver JDBC para MySQL:
Detalhamento:
- HikariCP: É o pool de conexões responsável por gerenciar a criação e reutilização de conexões com o banco de dados.
- SLF4J: É a API para log utilizada no código para registrar mensagens de log.
- MySQL Connector/J: Driver JDBC para conectar ao banco de dados MySQL.
Agora, ao adicionar essas dependências e configurações de módulo, você terá tudo configurado para gerenciar suas conexões com o banco de dados de forma eficiente usando HikariCP e SLF4J para logs. Se você estiver utilizando outro banco de dados, substitua a dependência do driver JDBC apropriado.
module br.com.professorclaytonandrade.sistemaservicojavafx {
requires javafx.controls;
requires javafx.fxml;
requires java.sql;
requires com.zaxxer.hikari; // HikariCP para gerenciamento de conexões
requires org.slf4j; // SLF4J para logging
// Abre o pacote para o JavaFX FXML para permitir injeção de dependências
opens br.com.professorclaytonandrade.sistemaservicojavafx to javafx.fxml;
// Exposição dos pacotes que precisam ser utilizados por outros módulos ou partes da aplicação
exports br.com.professorclaytonandrade.sistemaservicojavafx;
exports br.com.professorclaytonandrade.sistemaservicojavafx.controller;
// Abre o pacote controller para JavaFX FXML
opens br.com.professorclaytonandrade.sistemaservicojavafx.controller to javafx.fxml;
// Permite que o JavaFX use a serialização para manipular objetos DTO
opens br.com.professorclaytonandrade.sistemaservicojavafx.dto to javafx.base;
}
Código Java Controle de Versão Banco de Dados (Migration)
A classe InicializadorBancoDados
é responsável por gerenciar e aplicar migrações de banco de dados, assegurando que a estrutura do banco de dados esteja atualizada de acordo com scripts SQL definidos em arquivos de migração. Essa abordagem é comum em projetos que necessitam versionar mudanças no banco de dados, como a criação ou alteração de tabelas.
Descrição passo a passo:
Atributos da classe:
conexao
: Este atributo armazena uma instância deConnection
que é obtida pela classeFabricaDeConexao
. Ele representa a conexão ativa com o banco de dados.CAMINHO_MIGRACOES
: Define o caminho onde os arquivos SQL de migração estão armazenados. Neste exemplo, a pasta ésql/
.
Construtor:
- O construtor da classe invoca o método
FabricaDeConexao.obterConexao()
para estabelecer uma conexão com o banco de dados no momento em que uma instância deInicializadorBancoDados
é criada.
- O construtor da classe invoca o método
Método
inicializar
:- Função: Este método gerencia todo o processo de inicialização e migração do banco de dados.
- Ele cria a tabela de controle de versões, caso ela ainda não exista, usando o método
criarSchemaVersaoTabela()
. - Lista todos os arquivos de migração presentes na pasta definida (
sql/
), garantindo que eles sejam aplicados em ordem. - Para cada arquivo de migração, ele verifica se a migração já foi aplicada (consultando a tabela de controle de versões). Caso não tenha sido, ele lê o conteúdo do arquivo SQL e aplica a migração.
- Ele cria a tabela de controle de versões, caso ela ainda não exista, usando o método
- Função: Este método gerencia todo o processo de inicialização e migração do banco de dados.
Método
listarArquivosDeMigracao
:- Função: Lista todos os arquivos de migração SQL na pasta
sql/
e os retorna em uma lista. Os arquivos são ordenados para garantir que as migrações sejam aplicadas na sequência correta.
- Função: Lista todos os arquivos de migração SQL na pasta
Método
lerArquivoSql
:- Função: Lê o conteúdo de um arquivo SQL e o converte em uma string que será executada no banco de dados. Verifica se o arquivo não está vazio e lança uma exceção se o SQL estiver vazio.
Método
aplicarMigracao
:- Função: Executa o SQL de migração no banco de dados e registra a migração aplicada na tabela de controle de versões usando o método
registrarMigracao()
.
- Função: Executa o SQL de migração no banco de dados e registra a migração aplicada na tabela de controle de versões usando o método
Método
registrarMigracao
:- Função: Insere um registro na tabela
schema_version
, indicando que a migração foi aplicada, com o número da versão e uma descrição da migração.
- Função: Insere um registro na tabela
Método
isMigracaoAplicada
:- Função: Verifica se uma migração já foi aplicada, consultando a tabela
schema_version
. Ele retornatrue
se a migração já foi aplicada (ou seja, o número da versão já existe na tabela).
- Função: Verifica se uma migração já foi aplicada, consultando a tabela
Método
criarSchemaVersaoTabela
:- Função: Cria a tabela
schema_version
caso ela ainda não exista. Essa tabela é usada para controlar quais versões de migração foram aplicadas no banco de dados.
- Função: Cria a tabela
Método
extrairVersaoDoArquivo
:- Função: Extrai o número da versão a partir do nome do arquivo de migração. Por convenção, os arquivos de migração têm nomes como
V1__descricao.sql
, onde1
é o número da versão.
- Função: Extrai o número da versão a partir do nome do arquivo de migração. Por convenção, os arquivos de migração têm nomes como
Fluxo de execução:
Quando o método inicializar
é chamado, ele:
- Garante que a tabela de controle de versão existe.
- Lista todos os arquivos de migração SQL na pasta
sql/
. - Para cada arquivo:
- Extrai o número da versão.
- Verifica se a versão já foi aplicada.
- Se não foi aplicada, lê o arquivo SQL e aplica a migração no banco de dados.
- Registra a migração na tabela
schema_version
, garantindo que ela não será reaplicada no futuro.
Código Completo:
package br.com.professorclaytonandrade.sistemaservicojavafx.config.versoesbasedados;
import br.com.professorclaytonandrade.sistemaservicojavafx.config.conexao.FabricaDeConexao;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;
public class InicializadorBancoDados {
private final Connection conexao; // Conexão com o banco de dados
// Caminho onde os arquivos de migração estão localizados
private static final String CAMINHO_MIGRACOES = "sql/"; // Define o caminho das migrações
public InicializadorBancoDados() throws SQLException {
// Construtor que obtém a conexão com o banco de dados ao criar a instância
this.conexao = FabricaDeConexao.obterConexao();
}
public void inicializar() { // Método que inicia o processo de inicialização
try {
// Garante que a tabela de controle de versão existe
criarSchemaVersaoTabela();
// Lista e aplica os arquivos de migração
List arquivosMigracao = listarArquivosDeMigracao(); // Obtém a lista de arquivos de migração
// Percorre cada arquivo de migração
for (Path caminho : arquivosMigracao) {
// Extrai o número da versão a partir do nome do arquivo
int idVersao = extrairVersaoDoArquivo(caminho.getFileName().toString());
// Verifica se a migração já foi aplicada
if (!isMigracaoAplicada(idVersao)) {
// Lê o conteúdo do arquivo SQL
String sql = lerArquivoSql(caminho);
// Aplica a migração no banco de dados
aplicarMigracao(idVersao, caminho.getFileName().toString(), sql);
}
}
} catch (SQLException | IOException e) {
e.printStackTrace(); // Tratar exceções conforme necessário
}
}
private List listarArquivosDeMigracao() throws IOException {
try {
// Obtém a URL da pasta de migrações
URI uriMigracoes = getClass().getClassLoader().getResource(CAMINHO_MIGRACOES).toURI();
// Converte a URL para um objeto Path
Path diretorioMigracoes = Paths.get(uriMigracoes);
// Lista os arquivos no diretório de migrações
return Files.list(diretorioMigracoes)
.filter(Files::isRegularFile) // Filtra para obter apenas arquivos regulares
.sorted() // Ordena para garantir que as migrações sejam aplicadas na ordem correta
.collect(Collectors.toList()); // Coleta os resultados em uma lista
} catch (URISyntaxException e) {
throw new IOException("Erro ao acessar a pasta de migrações", e);
} catch (NullPointerException e) {
throw new IOException("Pasta de migrações não encontrada: " + CAMINHO_MIGRACOES);
// Mensagem de erro caso a pasta não exista
}
}
private String lerArquivoSql(Path caminhoArquivo) throws IOException, SQLException {
// Cria um StringBuilder para armazenar o conteúdo do arquivo SQL
StringBuilder sqlBuilder = new StringBuilder();
// Lê o conteúdo do arquivo SQL linha por linha
try (BufferedReader leitor = Files.newBufferedReader(caminhoArquivo)) {
String linha;
while ((linha = leitor.readLine()) != null) { // Continua lendo enquanto houver linhas
sqlBuilder.append(linha).append("\n"); // Adiciona a linha ao StringBuilder
}
}
String sql = sqlBuilder.toString().trim(); // Remove espaços em branco do início e fim
// Verifica se a string SQL não está vazia
if (sql.isEmpty()) {
throw new SQLException("A string SQL não pode estar vazia: " + caminhoArquivo.toString());
// Mensagem de erro se estiver vazia
}
return sql; // Retorna o conteúdo SQL lido
}
private void aplicarMigracao(int idVersao, String descricao, String sql) throws SQLException {
// Prepara a declaração SQL para a execução da migração
try (PreparedStatement declaracao = conexao.prepareStatement(sql)) {
declaracao.executeUpdate(); // Executa a atualização no banco de dados
// Registra a migração aplicada no controle de versão
registrarMigracao(idVersao, descricao);
}
}
private void registrarMigracao(int idVersao, String descricao) throws SQLException {
// SQL para registrar a migração na tabela de controle de versão
String sql = "INSERT INTO schema_version (version_id, description) VALUES (?, ?)";
try (PreparedStatement declaracao = conexao.prepareStatement(sql)) {
declaracao.setInt(1, idVersao); // Define o ID da versão
declaracao.setString(2, descricao); // Define a descrição da migração
declaracao.executeUpdate(); // Executa a inserção na tabela
}
}
private boolean isMigracaoAplicada(int idVersao) throws SQLException {
// SQL para verificar se a migração foi aplicada
String sql = "SELECT COUNT(*) FROM schema_version WHERE version_id = ?";
try (PreparedStatement declaracao = conexao.prepareStatement(sql)) {
declaracao.setInt(1, idVersao); // Define o ID da versão
var resultSet = declaracao.executeQuery(); // Executa a consulta
resultSet.next(); // Move para o próximo registro
// Retorna true se a migração foi aplicada (contagem maior que 0)
return resultSet.getInt(1) > 0;
}
}
private void criarSchemaVersaoTabela() throws SQLException {
// SQL para criar a tabela de controle de versão, se não existir
String sql = "CREATE TABLE IF NOT EXISTS schema_version (" +
"version_id INT PRIMARY KEY, " +
"description VARCHAR(255), " +
"applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)";
try (PreparedStatement declaracao = conexao.prepareStatement(sql)) {
declaracao.executeUpdate(); // Executa a criação da tabela
}
}
private int extrairVersaoDoArquivo(String arquivo) {
// Extrai o número da versão a partir do nome do arquivo (ex: V1__descricao.sql -> 1)
String parteVersao = arquivo.split("__")[0].substring(1); // Remove o 'V' e pega o número
return Integer.parseInt(parteVersao); // Retorna o número da versão como um inteiro
}
}
Código Java Mensagens
A classe Mensagens
serve como uma coleção de constantes de texto utilizadas em todo o sistema, facilitando a manutenção e a centralização das mensagens exibidas para o usuário em operações de salvamento, validação e erros. Cada constante representa um texto padrão que pode ser usado em diferentes partes da aplicação para padronizar mensagens.
Descrição das constantes:
TITULO_CONFIRMACAO_SALVAMENTO:
"Confirmação de Salvamento"
- Usada como título para caixas de diálogo ou notificações que pedem confirmação ao usuário antes de salvar alguma informação.
TITULO_ERRO_VALIDACAO:
"Erro de Validação"
- Usada como título para alertas de erro que aparecem quando há problemas de validação, ajudando a informar o usuário que alguma entrada de dados é inválida.
TITULO_ERRO_AO_SALVAR:
"Erro ao salvar:"
- Utilizada como título em mensagens de erro específicas quando ocorrem problemas durante o processo de salvamento de dados.
MSG_INF_SALVAS_COM_SUCESSO:
"As alterações foram salvas com sucesso."
- Mensagem exibida ao usuário indicando que o salvamento foi bem-sucedido e que as alterações foram aplicadas corretamente.
MSG_ERRO_AO_SALVAR_INFORMACOES:
"Ocorreu um erro ao salvar as informações:"
- Mensagem usada para notificar o usuário sobre uma falha no processo de salvamento, muitas vezes seguida de detalhes específicos do erro.
Benefícios do uso da classe Mensagens
:
- Centralização: Todas as mensagens estão em um único local, facilitando a manutenção e alteração futura.
- Padronização: Evita mensagens inconsistentes na interface, criando uma experiência mais uniforme para o usuário.
- Facilidade de Internacionalização: A classe permite adaptação para múltiplos idiomas, caso necessário, bastando trocar as mensagens em um só lugar.
Código Completo:
package br.com.professorclaytonandrade.sistemaservicojavafx.util;
public class Mensagens {
public static String TITULO_CONFIRMACAO_SALVAMENTO = "Confirmação de Salvamento ";
public static String TITULO_ERRO_VALIDACAO = "Erro de Validação ";
public static String TITULO_ERRO_AO_SALVAR = "Erro ao salvar: ";
public static String MSG_INF_SALVAS_COM_SUCESSO = "As alterações foram salvas com sucesso. ";
public static String MSG_ERRO_AO_SALVAR_INFORMACOES = "Ocorreu um erro ao salvar as informações: ";
}
Código Java Util
A classe Util
fornece métodos utilitários para lidar com a exibição de janelas modais e alertas no JavaFX, centralizando a lógica de manipulação de interfaces e facilitando a reutilização em toda a aplicação. Ela conta com métodos para carregar arquivos FXML, configurar janelas modais e exibir alertas personalizados.
Descrição dos métodos:
janelaModal:
- Abre uma nova janela modal sem dados adicionais.
- Parâmetros:
anchorPane
: Componente pai (para definir a posição e bloqueio da janela).telaFXML
: Caminho do arquivo FXML da nova janela.tituloJanela
: Título da nova janela.
- Usa
carregarFXML
para carregar o arquivo FXML ecriarPopupStage
para configurar a nova janela modal.
janelaModalComDados:
- Abre uma janela modal, enviando dados a um controlador específico.
- Parâmetros:
anchorPane
: Componente pai.telaFXML
: Caminho do FXML.tituloJanela
: Título da janela.objeto
: Dados a serem enviados.controller
: Controlador esperado.
- Atribui o objeto ao controlador usando reflexão para chamar o método
setDado
, permitindo que a janela exiba ou utilize os dados recebidos.
carregarFXML:
- Carrega e retorna um objeto
Parent
a partir de um arquivo FXML especificado. - Facilita a reutilização no código ao lidar com carregamento de arquivos FXML.
- Carrega e retorna um objeto
criarPopupStage:
- Cria e retorna um objeto
Stage
(janela) configurado com título, cena e relacionamento com o componente pai. - Parâmetros:
tituloJanela
: Define o título da nova janela.parent
: Layout da cena.anchorPane
: Define o componente que será o “dono” da nova janela.
- Cria e retorna um objeto
configurarJanela:
- Configura a janela como modal (usando
Modality.APPLICATION_MODAL
), centraliza na tela e define como não redimensionável.
- Configura a janela como modal (usando
exibirJanelaModal:
- Exibe a janela criada como um modal, esperando que o usuário interaja antes de continuar a execução.
exibirAlerta:
- Exibe um alerta do tipo especificado e retorna
true
se o usuário clicar em “OK”. - Parâmetros:
tipo
: Tipo de alerta (comoINFORMATION
ouERROR
).titulo
: Título do alerta.cabecalho
: Cabeçalho para contexto do alerta.conteudo
: Mensagem do alerta.
- Exibe um alerta do tipo especificado e retorna
Código Completo:
package br.com.professorclaytonandrade.sistemaservicojavafx.util;
import br.com.professorclaytonandrade.sistemaservicojavafx.StartApplication;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Util {
public static void janelaModal(AnchorPane anchorPane, String telaFXML,
String tituloJanela) throws IOException {
Parent parent = carregarFXML(telaFXML);
Stage popupStage = criarPopupStage(tituloJanela, parent, anchorPane);
configurarJanela(popupStage);
exibirJanelaModal(popupStage);
}
public static boolean janelaModalComDados(AnchorPane anchorPane, String telaFXML,
String tituloJanela, T objeto, Object controller) throws IOException {
// Carregar o arquivo FXML
FXMLLoader loader = new FXMLLoader(StartApplication.class.getResource(telaFXML));
Parent parent = loader.load();
// Obter o controlador do loader
Object loadedController = loader.getController();
// Verificar se o controlador passado é do tipo correto
if (controller != null && loadedController != null &&
controller.getClass() == loadedController.getClass()) {
// Supondo que o controlador tem um método setDado
try {
// Aqui usamos a classe do objeto para encontrar o método setDado
Method setDadoMethod = loadedController.getClass()
.getMethod("setDado", objeto.getClass());
setDadoMethod.invoke(loadedController, objeto);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException("Erro ao invocar o método setDado no controlador.");
}
} else {
throw new IllegalArgumentException("O controlador não corresponde
ao esperado ou não pôde ser carregado.");
}
// Criar e exibir a janela modal
Stage popupStage = criarPopupStage(tituloJanela, parent, anchorPane);
configurarJanela(popupStage);
exibirJanelaModal(popupStage);
return true;
}
// Carrega o arquivo FXML fornecido
private static Parent carregarFXML(String telaFXML) throws IOException {
return FXMLLoader.load(StartApplication.class.getResource(telaFXML));
}
// Cria o Stage (janela) para o popup
private static Stage criarPopupStage(String tituloJanela, Parent parent, AnchorPane anchorPane) {
Stage popupStage = new Stage();
popupStage.setTitle(tituloJanela);
Scene scene = new Scene(parent);
popupStage.setScene(scene);
popupStage.initOwner(anchorPane.getScene().getWindow());
return popupStage;
}
// Configura a janela, incluindo modal, centralização e redimensionamento
private static void configurarJanela(Stage popupStage) {
popupStage.initModality(Modality.APPLICATION_MODAL); // Mudança aqui para APPLICATION_MODAL
popupStage.centerOnScreen();
popupStage.setResizable(false);
}
// Exibe o Stage como um modal
private static void exibirJanelaModal(Stage popupStage) {
popupStage.showAndWait(); // Já está correto
}
public static boolean exibirAlerta(Alert.AlertType tipo, String titulo,
String cabecalho, String conteudo) {
Alert alert = new Alert(tipo);
alert.setTitle(titulo);
alert.setHeaderText(cabecalho);
alert.setContentText(conteudo);
// Mostrar o alerta e esperar a resposta do usuário
return alert.showAndWait().filter(response -> response == ButtonType.OK).isPresent();
}
}