[RESOLVIDO]JavaFX - Alternativa para LookUpComboBox com chave estrangeira - Quais as possíbilidades?

Bom dia a todos.
Estou saindo da programação Delphi e entrando em Java, JavaFX.
Já consegui desenvolver uma interface em JavaFX para uma aplicação CRUD mas estou esbarrando no problema em relação a chave estrangeria.
No Delphi usava o DbLookUpComboBox mas em JavaFX não existe este componente.
Eu até já consegui listar em um componente Choice Box do JavaFX os itens desejados da chave estrangeira, mas a questão que só é possível listar um único campo da tabela.
Por exemplo, em uma tabela de municípios onde tenho Mun_Cod (Primary Key) e Mun_Municipio, só consigo caregar no ChoiceBox um dos campos, ou o código ou a cdescrição do municipio. Tentei até atribuir o código ao Indice do item do Choice Box mas isso não é possível.
Bom, essa foi uma das tentativas, mas como JavaFx é outra linguagem, entendo que pode não ser possível trabalhar da mesma forma. Então gostaria de saber se alguém tem uma sugestão para gravar na tabela Master o código da detalhe, e também exibir na master a descrição do município para o usuário e não a chave estrangeira.

Cordialmente;

Claudir

Não sei se entendi o que você quis dizer, mas você pode usar o index selecionado da sua combobox e indexar uma lista, assim você pega o objeto…

É isso?

Bom dia Jesuino. Você é o mesmo Jesuino do javafree.uol.com.br?
Se for quero agradecer. Tem muito material bom lá sobre FavaFx. Li muitas coisas lá. :slight_smile:
Bom, deicha eu detalhar mais. Quanto a gravação na base até que eu consegui resolver fazendo uma “gambiarra”.
O que eu fiz:

Coloquei dois componentes choiche Box e coloquei o seguinte bind na propriedade “Items” de cada um deles:

Para Listar no choice Box os códigos dos municípios: contCidCod

for(record in jdbcDsCidade.getRecordSet().all()) record.get("CID_COD")

Para Listar no Choice Box os Nomes dos Municípios: contCidNome

for(record in jdbcDsCidade.getRecordSet().all()) record.getString("CID_NOME")

No Choice Box contCidNome coloquei o seguinte código para que quando selecionado a descrição do município ele já selecione no contCidCod o código correto:

function choiceNomeOnMouseExited(event: javafx.scene.input.MouseEvent): Void { //TODO contCidCod.select(contCidNome.selectedIndex); }

Depois coloquei o seguinte código em um botão para realizar um update na tabela:

function buttonAction(): Void { //TODO jdbcDataSource.execute("update tb_contatos set" " cont_nome='{contNome.rawText}'," " cont_logradouro='{contLogradouro.rawText}'," " cont_bairro='{contBairro.rawText}'," " cont_complemento='{contComplemento.rawText}'," " cont_observacao='{contObservacao.rawText}'," " cont_CidCod='{contCidCod.selectedItem}'" " where Cont_cod={contCod.text}"); jdbcDataSource.fetchData(); }

Com isso, gravar na tabela foi resolvido. Meu problema está sendo exibir a descrição da cidade e não o código em um TextBox.
Ou seja, estou usando os ChoiceBox para gravação e está dando certo. Só não estou conseguindo exibir a descrição do município em um TextBox. Veja na tela abaixo:

São nesses tipos de detalhes que vejo que o Java ainda precisa melhorar nas IDEs e componentes pra aperfeiçoar a produtividade. O Delphi pode ter vários defeitos, mas esse tipo de componente que é muito comum é muito simples de se trabalhar no Delphi.

Após muita leitura na net e ajuda do Jesuino, consegui resolver da seguinte forma:

Primeiro crio uma lista e faço bind com os valores do campo que é chave primária da tabela detalhe.

Depois crio um gatilho para que o choiceBox(contCidNome) que contém a descrição das cidades seja atualizado ao selecionar os registros. Dessa forma ele irá exibir o município informano para o contato:

def indice2 = bind Sequences.indexOf(listaCidCod,(jdbcDsContato.getRecordSet().currentString("CONT_CIDCOD"))) on replace{ contCidNome.select(indice2); }

Para facilicar o entendimento ai vai meu código na integra. Ressalto que estou usando o JavaFx Composer do NetBeans 6.9.

/*
 * Principal.fx
 *
 * Created on 09/06/2010, 14:37:34
 */

package javafxmysql;

import javax.swing.JOptionPane;
import javafx.scene.control.ChoiceBox;
import javafx.util.*;
import java.lang.System;



/**Path {
elements : [

]
}

 * @author claupers
 */

public class Principal {

    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    def __layoutInfo_contNome: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 421.0
    }
    public-read def contNome: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        layoutX: 39.0
        layoutY: 88.0
        layoutInfo: __layoutInfo_contNome
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_NOME")
        promptText: ""
    }
    
    public-read def tile: javafx.scene.layout.Tile = javafx.scene.layout.Tile {
        layoutX: 148.0
        layoutY: 124.0
        columns: 2
        hgap: 6.0
        vgap: 6.0
    }
    
    public-read def button: javafx.scene.control.Button = javafx.scene.control.Button {
        layoutX: 408.0
        layoutY: 290.0
        text: "Salvar"
        action: buttonAction
    }
    
    def __layoutInfo_contCod: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 34.0
    }
    public-read def contCod: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        disable: true
        layoutX: 39.0
        layoutY: 15.0
        layoutInfo: __layoutInfo_contCod
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_COD")
        editable: false
    }
    
    def __layoutInfo_indexNextButton: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        hfill: true
    }
    public-read def indexNextButton: javafx.scene.control.Button = javafx.scene.control.Button {
        disable: bind not jdbcDsContato.getRecordSet().hasNext()
        layoutX: 126.0
        layoutY: 290.0
        layoutInfo: __layoutInfo_indexNextButton
        text: "Next"
        action: function ():Void { jdbcDsContato.getRecordSet().next(); }
    }
    
    def __layoutInfo_indexPreviousButton: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        hfill: true
    }
    public-read def indexPreviousButton: javafx.scene.control.Button = javafx.scene.control.Button {
        disable: bind not jdbcDsContato.getRecordSet().hasPrev()
        layoutX: 25.0
        layoutY: 290.0
        layoutInfo: __layoutInfo_indexPreviousButton
        text: "Previous"
        action: function ():Void { jdbcDsContato.getRecordSet().prev(); }
    }
    
    public-read def label: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 45.0
        layoutY: 67.0
        text: "Nome"
    }
    
    def __layoutInfo_contLogradouro: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 285.0
    }
    public-read def contLogradouro: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        layoutX: 39.0
        layoutY: 157.0
        layoutInfo: __layoutInfo_contLogradouro
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_LOGRADOURO")
    }
    
    public-read def label2: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 39.0
        layoutY: 133.0
        text: "Logradouro"
    }
    
    def __layoutInfo_contBairro: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 122.0
    }
    public-read def contBairro: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        layoutX: 336.0
        layoutY: 157.0
        layoutInfo: __layoutInfo_contBairro
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_BAIRRO")
    }
    
    public-read def label3: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 336.0
        layoutY: 133.0
        text: "Bairro"
    }
    
    def __layoutInfo_contComplemento: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 235.0
    }
    public-read def contComplemento: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        layoutX: 39.0
        layoutY: 225.0
        layoutInfo: __layoutInfo_contComplemento
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_COMPLEMENTO")
    }
    
    public-read def label4: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 39.0
        layoutY: 210.0
        text: "Complemento"
    }
    
    def __layoutInfo_contObservacao: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 421.0
    }
    public-read def contObservacao: javafx.scene.control.TextBox = javafx.scene.control.TextBox {
        layoutX: 39.0
        layoutY: 261.0
        layoutInfo: __layoutInfo_contObservacao
        text: bind jdbcDsContato.getRecordSet().currentString("CONT_OBSERVACAO")
    }
    
    public-read def label5: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 45.0
        layoutY: 246.0
        text: "Observa\u00E7\u00E3o"
    }
    
    public-read def tooltip: javafx.scene.control.Tooltip = javafx.scene.control.Tooltip {
        text: "Selecione o Munic\u00EDpio do contato."
    }
    
    def __layoutInfo_contCidNome: javafx.scene.layout.LayoutInfo = javafx.scene.layout.LayoutInfo {
        width: 174.0
    }
    public-read def contCidNome: javafx.scene.control.ChoiceBox = javafx.scene.control.ChoiceBox {
        cursor: null
        layoutX: 284.0
        layoutY: 225.0
        layoutInfo: __layoutInfo_contCidNome
        effect: null
        tooltip: tooltip
        items: bind for(record in jdbcDsCidade.getRecordSet().all())"{record.get("CID_COD")}{" - "} {record.get("CID_NOME")}{"/"} {record.get("CID_UF")}"
    }
    
    public-read def button2: javafx.scene.control.Button = javafx.scene.control.Button {
        layoutX: 246.0
        layoutY: 290.0
        text: "Button"
        action: button2Action
    }
    
    public-read def label6: javafx.scene.control.Label = javafx.scene.control.Label {
        layoutX: 288.0
        layoutY: 210.0
        text: "Cidade"
    }
    
    public-read def color: javafx.scene.paint.Color = javafx.scene.paint.Color {
        red: 0.16078432
        green: 0.49019608
        blue: 0.6
    }
    
    public-read def scene: javafx.scene.Scene = javafx.scene.Scene {
        width: 480.0
        height: 320.0
        content: getDesignRootNodes ()
        camera: null
        fill: color
    }
    
    public-read def jdbcDsContato: org.netbeans.javafx.datasrc.DbDataSource = org.netbeans.javafx.datasrc.DbDataSource {
        connectionString: "jdbc:mysql://localhost:3306/agenda"
        user: "root"
        password: "SENHA"
        query: "select * from tb_contatos"
    }
    
    public-read def jdbcDsCidade: org.netbeans.javafx.datasrc.DbDataSource = org.netbeans.javafx.datasrc.DbDataSource {
        connectionString: "jdbc:mysql://localhost:3306/agenda"
        user: "root"
        password: "SENHA"
        query: "select * from tb_cidade"
    }
    
    public-read def currentState: org.netbeans.javafx.design.DesignState = org.netbeans.javafx.design.DesignState {
    }
    
    public function getDesignRootNodes (): javafx.scene.Node[] {
        [ contNome, tile, button, contCod, indexNextButton, indexPreviousButton, label, contLogradouro, label2, contBairro, label3, contComplemento, label4, contObservacao, label5, contCidNome, button2, label6, ]
    }
    
    public function getDesignScene (): javafx.scene.Scene {
        scene
    }
    // </editor-fold>
    
    function buttonAction(): Void {
        //TODO
        jdbcDsContato.execute("update tb_contatos set"
           " cont_nome='{contNome.rawText}',"
           " cont_logradouro='{contLogradouro.rawText}',"
           " cont_bairro='{contBairro.rawText}',"
           " cont_complemento='{contComplemento.rawText}',"
           " cont_observacao='{contObservacao.rawText}',"
           " cont_CidCod='{listaCidCod[contCidNome.selectedIndex]}'"
           " where Cont_cod={contCod.text}");
        jdbcDsContato.fetchData();

       JOptionPane.showMessageDialog(null,listaCidCod[contCidNome.selectedIndex]);
         }
def listaCidCod = bind {for(record in jdbcDsCidade.getRecordSet().all()) (record.get("CID_COD").toString())};


def indice2 = bind Sequences.indexOf(listaCidCod,(jdbcDsContato.getRecordSet().currentString("CONT_CIDCOD"))) on replace{
    contCidNome.select(indice2);
}

}

function run (): Void {



var design = Principal {};

    javafx.stage.Stage {
        title: "Principal"
        scene: design.getDesignScene ()



    }
}

O unico bug no código que não consegui corrigir foi o fato de ao abrir a tela o sistema não conseguir pegar o código do primeiro registro, ai ele acaba não exibindo a descrição da cidade no choicebox. Dessa forma antes de alterar a linha que faz bind para a lista para gerar string o mesmo retornava erro de conversão do valor por ser uma string vazia, por isso adicionei o parametro tostring no final:

É isso ai pessoal. Se alguém conseguir resolver esse bug posta ai para nós.

Cordialmente;