User:DressyPear4/MostraTeclasPressionadas

From OpenStreetMap Wiki
Jump to navigation Jump to search

Mostrar teclas pressionadas

Ideal para gravação de tutoriais, facilita na identificação principalmente de atalhos. Você pode escolher entre;

  • Janela Simples (sem mouse)
  • Janela com histórico
  • Barra compacta

Como funciona?

  • Executar o script
  • Uma janela irá aparecer, pode ser movida para qualquer posição.

Demonstração

Imagem.gif, clique para visualizar.

Código

Janela simples
from javax.swing import JDialog, JLabel, JPanel, BoxLayout, BorderFactory, Timer
from java.awt import Font, Color, KeyboardFocusManager, KeyEventDispatcher, Toolkit
from java.awt.event import KeyEvent, ActionListener
from java.lang import Runnable, Thread
from org.openstreetmap.josm.gui import MainApplication

COR_PADRAO = Color(99, 99, 99)
COR_ATIVA = Color(255, 255, 255)

class TecladoVisualizador(JDialog, Runnable):
    def __init__(self):
        super(TecladoVisualizador, self).__init__(MainApplication.getMainFrame(), False)

    def run(self):
        self.setTitle("Teclas pressionadas")
        self.setSize(300, 125)
        self.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)

        screen_size = Toolkit.getDefaultToolkit().getScreenSize()
        x = screen_size.width - self.getWidth() - 0
        y = screen_size.height - self.getHeight() - 45
        self.setLocation(x, y)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

        self.mod_panel = JPanel()
        self.lbl_ctrl = self.criar_botao("Ctrl")
        self.lbl_alt = self.criar_botao("Alt")
        self.lbl_shift = self.criar_botao("Shift")

        self.mod_panel.add(self.lbl_ctrl)
        self.mod_panel.add(self.lbl_alt)
        self.mod_panel.add(self.lbl_shift)

        self.lbl_tecla = self.criar_botao("", tamanho=32)
        self.lbl_tecla.setAlignmentX(JLabel.CENTER_ALIGNMENT)

        panel.add(self.mod_panel)
        panel.add(self.lbl_tecla)
        self.add(panel)
        self.setVisible(True)

        self.timer = Timer(1500, self.LimparTeclaAction(self))
        self.timer.setRepeats(False)

        self.dispatcher = self.TeclaDispatcher(self)
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(self.dispatcher)

    def criar_botao(self, texto, tamanho=20):
        lbl = JLabel("  " + texto + "  ")
        lbl.setFont(Font("Arial", Font.BOLD, tamanho))
        lbl.setForeground(COR_PADRAO)
        lbl.setOpaque(True)
        lbl.setBorder(BorderFactory.createLineBorder(COR_PADRAO, 2))
        return lbl

    def destacar(self, label):
        label.setForeground(COR_ATIVA)
        label.setBorder(BorderFactory.createLineBorder(COR_ATIVA, 2))

    def padronizar(self, label):
        label.setForeground(COR_PADRAO)
        label.setBorder(BorderFactory.createLineBorder(COR_PADRAO, 2))

    class LimparTeclaAction(ActionListener):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def actionPerformed(self, e):
            self.visualizador.lbl_tecla.setText("")
            self.visualizador.padronizar(self.visualizador.lbl_tecla)

    class TeclaDispatcher(KeyEventDispatcher):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def dispatchKeyEvent(self, e):
            if e.getID() == KeyEvent.KEY_PRESSED:
                nome = KeyEvent.getKeyText(e.getKeyCode())

                if KeyEvent.VK_NUMPAD0 <= e.getKeyCode() <= KeyEvent.VK_NUMPAD9:
                    nome = str(e.getKeyCode() - KeyEvent.VK_NUMPAD0)
                elif e.getKeyCode() == KeyEvent.VK_DECIMAL:
                    nome = "."

                if nome not in ["Ctrl", "Alt", "Shift", "Control", "Alt Graph"]:
                    self.visualizador.lbl_tecla.setText("  " + nome.upper() + "  ")
                    self.visualizador.destacar(self.visualizador.lbl_tecla)
                    self.visualizador.timer.restart()

                if nome in ["Ctrl", "Control"]:
                    self.visualizador.destacar(self.visualizador.lbl_ctrl)
                if nome == "Alt":
                    self.visualizador.destacar(self.visualizador.lbl_alt)
                if nome == "Shift":
                    self.visualizador.destacar(self.visualizador.lbl_shift)

            elif e.getID() == KeyEvent.KEY_RELEASED:
                nome = KeyEvent.getKeyText(e.getKeyCode())
                if nome in ["Ctrl", "Control"]:
                    self.visualizador.padronizar(self.visualizador.lbl_ctrl)
                if nome == "Alt":
                    self.visualizador.padronizar(self.visualizador.lbl_alt)
                if nome == "Shift":
                    self.visualizador.padronizar(self.visualizador.lbl_shift)

            return False

Thread(TecladoVisualizador()).start()
Janela com histórico
from javax.swing import JDialog, JLabel, JPanel, BoxLayout, BorderFactory, Timer, JTextArea
from java.awt import Font, Color, KeyboardFocusManager, KeyEventDispatcher, Toolkit, Dimension, AWTEvent
from java.awt.event import KeyEvent, ActionListener, MouseEvent, AWTEventListener
from java.lang import Runnable, Thread
from org.openstreetmap.josm.gui import MainApplication

COR_PADRAO = Color(99, 99, 99)
COR_ATIVA = Color(255, 255, 255)

class TecladoVisualizador(JDialog, Runnable):
    def __init__(self):
        super(TecladoVisualizador, self).__init__(MainApplication.getMainFrame(), False)

    def run(self):
        self.setTitle("Teclas pressionadas")
        self.setSize(325, 250)
        self.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)

        screen_size = Toolkit.getDefaultToolkit().getScreenSize()
        x = screen_size.width - self.getWidth() - 0
        y = screen_size.height - self.getHeight() - 45
        self.setLocation(x, y)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

        self.area_historico = JTextArea(6, 20)
        self.area_historico.setEditable(False)
        self.area_historico.setFont(Font("Monospaced", Font.PLAIN, 14))
        self.area_historico.setMaximumSize(Dimension(280, 100))
        panel.add(self.area_historico)

        self.mod_panel = JPanel()
        self.lbl_mouse_left = self.criar_botao("<L")
        self.lbl_mouse_right = self.criar_botao("R>")
        self.lbl_ctrl = self.criar_botao("Ctrl")
        self.lbl_alt = self.criar_botao("Alt")
        self.lbl_shift = self.criar_botao("Shift")

        self.mod_panel.add(self.lbl_mouse_left)
        self.mod_panel.add(self.lbl_mouse_right)
        self.mod_panel.add(self.lbl_ctrl)
        self.mod_panel.add(self.lbl_alt)
        self.mod_panel.add(self.lbl_shift)

        self.lbl_tecla = self.criar_botao("", tamanho=32)
        self.lbl_tecla.setAlignmentX(JLabel.CENTER_ALIGNMENT)

        panel.add(self.mod_panel)
        panel.add(self.lbl_tecla)
        self.add(panel)
        self.setVisible(True)

        self.timer = Timer(1500, self.LimparTeclaAction(self))
        self.timer.setRepeats(False)

        self.dispatcher = self.TeclaDispatcher(self)
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(self.dispatcher)

        self.historico = []
        Toolkit.getDefaultToolkit().addAWTEventListener(self.MouseListener(self), AWTEvent.MOUSE_EVENT_MASK)

    def criar_botao(self, texto, tamanho=20):
        lbl = JLabel("  " + texto + "  ")
        lbl.setFont(Font("Arial", Font.BOLD, tamanho))
        lbl.setForeground(COR_PADRAO)
        lbl.setOpaque(True)
        lbl.setBorder(BorderFactory.createLineBorder(COR_PADRAO, 2))
        return lbl

    def destacar(self, label):
        label.setForeground(COR_ATIVA)
        label.setBorder(BorderFactory.createLineBorder(COR_ATIVA, 2))

    def padronizar(self, label):
        label.setForeground(COR_PADRAO)
        label.setBorder(BorderFactory.createLineBorder(COR_PADRAO, 2))

    def adicionar_historico(self, texto):
        self.historico.append(texto)
        if len(self.historico) > 6:
            self.historico = self.historico[-6:]
        self.area_historico.setText("\n".join(self.historico))

    class LimparTeclaAction(ActionListener):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def actionPerformed(self, e):
            self.visualizador.lbl_tecla.setText("")
            self.visualizador.padronizar(self.visualizador.lbl_tecla)

    class TeclaDispatcher(KeyEventDispatcher):
        def __init__(self, visualizador):
            self.visualizador = visualizador
            self.ctrl_ativa = False
            self.alt_ativa = False
            self.shift_ativa = False

        def dispatchKeyEvent(self, e):
            nome = KeyEvent.getKeyText(e.getKeyCode())

            if e.getID() == KeyEvent.KEY_PRESSED:
                if nome in ["Ctrl", "Control"]:
                    self.ctrl_ativa = True
                    self.visualizador.destacar(self.visualizador.lbl_ctrl)
                elif nome == "Alt":
                    self.alt_ativa = True
                    self.visualizador.destacar(self.visualizador.lbl_alt)
                elif nome == "Shift":
                    self.shift_ativa = True
                    self.visualizador.destacar(self.visualizador.lbl_shift)
                else:
                    self.visualizador.lbl_tecla.setText("  " + nome.upper() + "  ")
                    self.visualizador.destacar(self.visualizador.lbl_tecla)
                    self.visualizador.timer.restart()

                    combinacao = []
                    if self.ctrl_ativa: combinacao.append("Ctrl")
                    if self.alt_ativa: combinacao.append("Alt")
                    if self.shift_ativa: combinacao.append("Shift")
                    combinacao.append(nome.upper())

                    self.visualizador.adicionar_historico("+".join(combinacao))

            elif e.getID() == KeyEvent.KEY_RELEASED:
                if nome in ["Ctrl", "Control"]:
                    self.ctrl_ativa = False
                    self.visualizador.padronizar(self.visualizador.lbl_ctrl)
                elif nome == "Alt":
                    self.alt_ativa = False
                    self.visualizador.padronizar(self.visualizador.lbl_alt)
                elif nome == "Shift":
                    self.shift_ativa = False
                    self.visualizador.padronizar(self.visualizador.lbl_shift)

            return False

    class MouseListener(AWTEventListener):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def eventDispatched(self, event):
            if isinstance(event, MouseEvent):
                if event.getID() == MouseEvent.MOUSE_PRESSED:
                    if event.getButton() == MouseEvent.BUTTON1:
                        self.visualizador.destacar(self.visualizador.lbl_mouse_left)
                        self.visualizador.adicionar_historico("Mouse Left")
                    elif event.getButton() == MouseEvent.BUTTON3:
                        self.visualizador.destacar(self.visualizador.lbl_mouse_right)
                        self.visualizador.adicionar_historico("Mouse Right")
                elif event.getID() == MouseEvent.MOUSE_RELEASED:
                    if event.getButton() == MouseEvent.BUTTON1:
                        self.visualizador.padronizar(self.visualizador.lbl_mouse_left)
                    elif event.getButton() == MouseEvent.BUTTON3:
                        self.visualizador.padronizar(self.visualizador.lbl_mouse_right)

Thread(TecladoVisualizador()).start()
Barra
from javax.swing import JDialog, JLabel, Timer
from javax.swing.border import LineBorder
from java.awt import Color, Font, Toolkit, GraphicsEnvironment, Point, AWTEvent
from java.awt.event import KeyEvent, ActionListener, AWTEventListener, MouseEvent, MouseAdapter, MouseMotionAdapter
from org.openstreetmap.josm.gui import MainApplication

class TecladoVisualizador(JDialog):
    def __init__(self):
        # Dialog não modal, pai = janela principal do JOSM
        super(TecladoVisualizador, self).__init__(MainApplication.getMainFrame(), False)

        self.setUndecorated(True)
        self.setAlwaysOnTop(False)
        self.setSize(675, 50)
        self.setLayout(None)

        # Posicionar sobre a tela principal
        screen = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds()
        self.setLocation(
            (screen.width * 6 // 10) - (self.getWidth()) // 2,
            screen.height - self.getHeight() - 70
        )

        # Labels de teclas e mouse
        self.lbl_lmb = self.criarLabel(10)
        self.lbl_rmb = self.criarLabel(80)
        self.lbl_alt = self.criarLabel(170)
        self.lbl_ctrl = self.criarLabel(240)
        self.lbl_shift = self.criarLabel(310)
        self.lbl_tecla = self.criarLabel(400, largura=230)

        # Botão fechar [X]
        self.lbl_fechar = JLabel("X", JLabel.CENTER)
        self.lbl_fechar.setBounds(650, 10, 15, 30)
        self.lbl_fechar.setFont(Font("Arial", Font.BOLD, 20))
        self.lbl_fechar.setForeground(Color.RED)
        self.lbl_fechar.setOpaque(False)
        self.lbl_fechar.addMouseListener(self.FecharListener(self))
        self.add(self.lbl_fechar)

        # Timer para limpar teclas
        self.timer = Timer(1000, self.LimparAction(self))
        self.timer.setRepeats(False)

        # Estado inicial
        self.lmb = False
        self.rmb = False
        self.alt = False
        self.ctrl = False
        self.shift = False
        self.tecla = ""

        # Fontes para lbl_tecla
        self.fonte_tecla_normal = Font("Arial", Font.BOLD, 20)
        self.fonte_tecla_ampliada = Font("Arial", Font.BOLD, 28)

        # Escutadores globais para teclas e mouse
        Toolkit.getDefaultToolkit().addAWTEventListener(
            self.GlobalListener(self),
            AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK
        )

        # Movimento da janela (arrastar)
        self.addMouseListener(self.ArrastarListener(self))
        self.addMouseMotionListener(self.ArrastarMovimento(self))

        self.atualizarLabels()

        self.setVisible(True)

    def criarLabel(self, x, largura=60):
        lbl = JLabel("", JLabel.CENTER)
        lbl.setBounds(x, 5, largura, 40)
        lbl.setFont(Font("Arial", Font.BOLD, 20))
        lbl.setBorder(LineBorder(Color(125, 125, 125), 2))
        lbl.setOpaque(False)
        lbl.setForeground(Color(125, 125, 125))
        self.add(lbl)
        return lbl

    def atualizarLabels(self):
        self.atualizar(self.lbl_lmb, "<L", self.lmb)
        self.atualizar(self.lbl_rmb, "R>", self.rmb)
        self.atualizar(self.lbl_alt, "Alt", self.alt)
        self.atualizar(self.lbl_ctrl, "Ctrl", self.ctrl)
        self.atualizar(self.lbl_shift, "Shift", self.shift)

        if self.tecla:
            self.lbl_tecla.setFont(self.fonte_tecla_ampliada)
        else:
            self.lbl_tecla.setFont(self.fonte_tecla_normal)

        self.atualizar(self.lbl_tecla, self.tecla if self.tecla else "", bool(self.tecla))

    def atualizar(self, lbl, texto, ativo):
        lbl.setText(texto)
        if ativo:
            lbl.setForeground(Color.WHITE)
            lbl.setBorder(LineBorder(Color.WHITE, 2))
        else:
            lbl.setForeground(Color(125, 125, 125))
            lbl.setBorder(LineBorder(Color(125, 125, 125), 2))

    class GlobalListener(AWTEventListener):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def eventDispatched(self, event):
            v = self.visualizador

            if isinstance(event, KeyEvent):
                if event.getID() == KeyEvent.KEY_PRESSED:
                    v.alt = event.isAltDown()
                    v.ctrl = event.isControlDown()
                    v.shift = event.isShiftDown()

                    code = event.getKeyCode()

                    if KeyEvent.VK_NUMPAD0 <= code <= KeyEvent.VK_NUMPAD9:
                        v.tecla = str(code - KeyEvent.VK_NUMPAD0)
                    elif code == KeyEvent.VK_DECIMAL:
                        v.tecla = "."
                    elif code == KeyEvent.VK_ADD:
                        v.tecla = "+"
                    elif code == KeyEvent.VK_SUBTRACT:
                        v.tecla = "-"
                    elif code == KeyEvent.VK_MULTIPLY:
                        v.tecla = "*"
                    elif code == KeyEvent.VK_DIVIDE:
                        v.tecla = "/"
                    elif code not in [KeyEvent.VK_ALT, KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT,
                                      KeyEvent.VK_ALT_GRAPH]:
                        v.tecla = KeyEvent.getKeyText(code)
                    else:
                        v.tecla = ""

                    v.atualizarLabels()
                    v.timer.restart()

            elif isinstance(event, MouseEvent):
                if event.getID() == MouseEvent.MOUSE_PRESSED:
                    if event.getButton() == MouseEvent.BUTTON1:
                        v.lmb = True
                    elif event.getButton() == MouseEvent.BUTTON3:
                        v.rmb = True
                    v.atualizarLabels()

                elif event.getID() == MouseEvent.MOUSE_RELEASED:
                    if event.getButton() == MouseEvent.BUTTON1:
                        v.lmb = False
                    elif event.getButton() == MouseEvent.BUTTON3:
                        v.rmb = False
                    v.atualizarLabels()

    class LimparAction(ActionListener):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def actionPerformed(self, e):
            v = self.visualizador
            v.alt = False
            v.ctrl = False
            v.shift = False
            v.tecla = ""
            v.lbl_tecla.setFont(v.fonte_tecla_normal)
            v.atualizarLabels()

    class FecharListener(MouseAdapter):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def mouseClicked(self, e):
            self.visualizador.dispose()

    class ArrastarListener(MouseAdapter):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def mousePressed(self, e):
            self.visualizador.ponto_inicial = e.getPoint()

    class ArrastarMovimento(MouseMotionAdapter):
        def __init__(self, visualizador):
            self.visualizador = visualizador

        def mouseDragged(self, e):
            ponto = e.getLocationOnScreen()
            deslocamento = self.visualizador.ponto_inicial
            self.visualizador.setLocation(ponto.x - deslocamento.x, ponto.y - deslocamento.y)

# Executar o visualizador
TecladoVisualizador()