NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Java Swing

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
dinokino
Člen
Avatar
dinokino:19.12.2015 19:03

Dobrý den, učím se podle zdejších návodů, konkrétně Java->Tvorba her v Java Swing. Narazil jsem u 6. dílu o událostech typu KeyEvent. V tutoriálu se píše: ,,Aby komponenta mohla generovat události KeyEvent, musí mít zaměření (focus)". Autor tím míní, že je potřeba použít metodu setFocusable(). Předpokládám, že můj problém spočívá právě v této metodě. Mám hlavní třídu, která zároveň funguje jako okno programu:

package Game;
import javax.swing.*;
public class Game extends JFrame{
        DrawPanel dp;
Game(){
        dp = new DrawPanel();
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
        this.add(dp);
        this.pack();
}
        public static void main(String[] args) {
                Game g = new Game();

        }

}

Dále mám v programu třídu, která rozšiřuje třídu "JPanel", a která je v programu použita jako "obsah" okna programu. Myslím tím to, že je tato třída přidána do kontejneru "Game" a tvoří kontejner pro další prvky (tedy pouze prvek JLabel).

package Game;
import javax.swing.*;
import java.awt.*;
public class DrawPanel extends JPanel {
JLabel text;
        DrawPanel(){
                this.setFocusable(true);
                this.setPreferredSize(new Dimension(200,300));
                text = new JLabel("a");
                this.add(text);
                KeyList kl = new KeyList(text);
                this.addKeyListener(kl);
        }


}

Ještě mám definovanou třídu pro obsluhu událostí "KeyList":

package Game;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;

public class KeyList implements KeyListener{
        JLabel text;
KeyList(JLabel t){
        text = t;
}
        @Override
        public void keyPressed(KeyEvent arg0) {
                text.setText("Klávesa stisknuta");

        }

        @Override
        public void keyReleased(KeyEvent arg0) {
                text.setText("Klávesa  puštěna");

        }

        @Override
        public void keyTyped(KeyEvent arg0) {
                // TODO Auto-generated method stub

        }

}

Problém spočívá v tom, že program po zkompilování funguje jen "když se mu chce"...Měl by při stisku klávesy vypsat (změnit text v okně na): "Klávesa stisknuta", po "puštění" klávesy zase: "Klávesa puštěna". Tohle se ale děje jen "občas". Prostě aby se měnil text v okně, tak program musím zkompilovat třeba 5*...:o jinak zůstane v okně výchozí text ("a"). To samé se děje i u vytvořeného jar souboru. Neví prosím někdo co je špatně? :o :(

 
Odpovědět
19.12.2015 19:03
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na dinokino
Atrament:19.12.2015 19:32

Aby komponenta mohla generovat události KeyEvent, musí mít zaměření (focus)". Autor tím míní, že je potřeba použít metodu setFocusable().

To autor nejspíš nemíní, protože setFocusable() nastavuje, že komponenta může získat focus, ne že ho bude automaticky mít. Pokud chceš aby měla nějaká komponenta focus hned po otevření okna, tak na ní spusť requestFocusIn­Window()

 
Nahoru Odpovědět
19.12.2015 19:32
Avatar
dinokino
Člen
Avatar
dinokino:19.12.2015 20:16

Alé já sem se celkem "věrně" držel tutoriálu... :D A tam se nic o metodě requestFocusIn­Window() nepsalo :D Tomu týpkovi to šlo prakticky skoro se stejným kódem, jako jsem napsal já...tak mě zajímá, kde jsem udělal chybu, protože autor toho tutoriálu nepsal, že mu to šlo na každé 3 až 5. spuštění...:o

 
Nahoru Odpovědět
19.12.2015 20:16
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na dinokino
Atrament:19.12.2015 20:51

V tom případě tam má autor chybu, setFocusable nezískává focus to dělá requestFocusIn­Window. Všiml jsem si, že autor toho tutoriálu použil jenom JPanel, takže tam není nic jiného co by mohlo získavat focus, tudíž mu to fungovalo, ty to ale dáváš ještě do JFrame, hádám že se ti to pak daří někdy pustit s focusem na JFrame a někdy nějakým způsobem na tom JPanel

 
Nahoru Odpovědět
19.12.2015 20:51
Avatar
dinokino
Člen
Avatar
dinokino:19.12.2015 23:18

Tak jsem "zkopíroval" soubory přiložené k tutoriálu a zjistil jsem, že u autorovy verze mi to dělá to samo...občas to funguje občas ne... :( Neví někdo co s tím? :O

 
Nahoru Odpovědět
19.12.2015 23:18
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na dinokino
Atrament:20.12.2015 0:08

Taky jsem si to zkusil a funguje mi to přesně jak má. Nebude v tom případě chyba někde úplně jinde? Na jakém systému to zkoušíš?

 
Nahoru Odpovědět
20.12.2015 0:08
Avatar
dinokino
Člen
Avatar
dinokino:20.12.2015 11:28

Systému myšleno operačním systému? :D Windows XP :D a jinak IDE používám netbeans.

 
Nahoru Odpovědět
20.12.2015 11:28
Avatar
dinokino
Člen
Avatar
dinokino:20.12.2015 13:45

Pro upřesnění co mám za problém posílám gif. Program fungoval až po 3. spuštění (po každém spuštění jsem párkrát stiskl klávesu).

 
Nahoru Odpovědět
20.12.2015 13:45
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na dinokino
Atrament:20.12.2015 14:17

Hm divný, jak říkám, mně ten samý kód funguje správně hned vždycky napoprvé na Windows 10, taky to pouštím z Netbeans. Co kdybys zkusil do konstruktoru PanelUdalosti hned za this.setFocusa­ble(true) doplnit this.requestFo­cusInWindow()? Nepomohlo by to?

 
Nahoru Odpovědět
20.12.2015 14:17
Avatar
dinokino
Člen
Avatar
dinokino:20.12.2015 19:50

Tak to nepomohlo...Rozhodl jsem se, že budu postupně můj kód "přetvářet" na kód identický s kódem v návodě... :D Zjistil jsem totiž, že mi přiložené zdrojové soubory jdou (omlouvám se, špatně jsem je "zkopíroval")...
A chyba byla v hlavní třídě, která rozšiřovala JFrame:

Game(){
        dp = new DrawPanel();
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
        this.add(dp);
        this.pack();
}

^ Tohle je původní kód. Po přehození řádku:

this.setVisible(true);

a:

this.add(dp);

Vše fungovalo jak má... :D Kvůli téhle blbosti jsem to už chtěl vzdát :D Může mi prosím někdo říct proč konkrétně zde záleží, jestli první přidám třídu, která rozšiřuje JPanel, anebo jestli první uvedu, aby se JFrame zviditelnil? Napadá mě, jestli to není tím, že když "zviditelním" JFrame, tak je to jakoby do přidání toho JPanelu do programu jediná komponenta a proto se na ní nastaví ten focus...Je to tím? A případně, jde "přenastavit" z JFrame? (kdybych chtěl zachovat původní kód...jen tak mě to zajímá...). Zkoušel jsem tu metodu requestFocusIn­Window(), ale to nepomohlo...

 
Nahoru Odpovědět
20.12.2015 19:50
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.