first commit
This commit is contained in:
7
Awesome_API/.vscode/settings.json
vendored
Normal file
7
Awesome_API/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"java.project.sourcePaths": ["src"],
|
||||||
|
"java.project.outputPath": "bin",
|
||||||
|
"java.project.referencedLibraries": [
|
||||||
|
"lib/**/*.jar"
|
||||||
|
]
|
||||||
|
}
|
||||||
18
Awesome_API/README.md
Normal file
18
Awesome_API/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code.
|
||||||
|
|
||||||
|
## Folder Structure
|
||||||
|
|
||||||
|
The workspace contains two folders by default, where:
|
||||||
|
|
||||||
|
- `src`: the folder to maintain sources
|
||||||
|
- `lib`: the folder to maintain dependencies
|
||||||
|
|
||||||
|
Meanwhile, the compiled output files will be generated in the `bin` folder by default.
|
||||||
|
|
||||||
|
> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there.
|
||||||
|
|
||||||
|
## Dependency Management
|
||||||
|
|
||||||
|
The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies).
|
||||||
BIN
Awesome_API/bin/Main$1.class
Normal file
BIN
Awesome_API/bin/Main$1.class
Normal file
Binary file not shown.
BIN
Awesome_API/bin/Main$2.class
Normal file
BIN
Awesome_API/bin/Main$2.class
Normal file
Binary file not shown.
BIN
Awesome_API/bin/Main.class
Normal file
BIN
Awesome_API/bin/Main.class
Normal file
Binary file not shown.
334
Awesome_API/src/Main.java
Normal file
334
Awesome_API/src/Main.java
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
|
public class Main extends JFrame {
|
||||||
|
|
||||||
|
// Cores do Design Moderno
|
||||||
|
private static final Color COLOR_BG_TOP = new Color(138, 180, 248);
|
||||||
|
private static final Color COLOR_BG_BOTTOM = new Color(25, 103, 210);
|
||||||
|
private static final Color COLOR_CARD = new Color(255, 255, 255, 220);
|
||||||
|
private static final Color COLOR_BTN_PRIMARY = new Color(242, 186, 45);
|
||||||
|
private static final Color COLOR_BTN_SECONDARY = new Color(219, 68, 55);
|
||||||
|
|
||||||
|
// Dados limpos
|
||||||
|
private String[] moedaDisplay = {
|
||||||
|
"Dólar Americano (USD)", "Euro (EUR)", "Real Brasileiro (BRL)",
|
||||||
|
"Libra Esterlina (GBP)", "Iene Japonês (JPY)", "Dólar Canadense (CAD)",
|
||||||
|
"Dólar Australiano (AUD)", "Franco Suíço (CHF)"
|
||||||
|
};
|
||||||
|
private String[] moedaAbrev = {"USD", "EUR", "BRL", "GBP", "JPY", "CAD", "AUD", "CHF"};
|
||||||
|
|
||||||
|
private JComboBox<String> cmbFrom;
|
||||||
|
private JComboBox<String> cmbTo;
|
||||||
|
private JTextField txtValue;
|
||||||
|
private JLabel lblResult;
|
||||||
|
private JLabel lblResultSub;
|
||||||
|
|
||||||
|
// Texto de Exemplo (Placeholder)
|
||||||
|
private final String PLACEHOLDER_TEXT = "Ex: 100.00";
|
||||||
|
|
||||||
|
public Main() {
|
||||||
|
setTitle("Conversor de Moedas");
|
||||||
|
setSize(420, 750);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
|
||||||
|
// Painel Principal com Gradiente Azul
|
||||||
|
JPanel mainPanel = new JPanel() {
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
GradientPaint gp = new GradientPaint(0, 0, COLOR_BG_TOP, 0, getHeight(), COLOR_BG_BOTTOM);
|
||||||
|
g2.setPaint(gp);
|
||||||
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
||||||
|
mainPanel.setBorder(new EmptyBorder(20, 20, 20, 20));
|
||||||
|
setContentPane(mainPanel);
|
||||||
|
|
||||||
|
// --- TÍTULO ---
|
||||||
|
JLabel title = new JLabel("Conversor de Moedas", SwingConstants.CENTER);
|
||||||
|
title.setFont(new Font("Segoe UI", Font.BOLD, 30));
|
||||||
|
title.setForeground(Color.WHITE);
|
||||||
|
title.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
mainPanel.add(title);
|
||||||
|
mainPanel.add(Box.createVerticalStrut(20));
|
||||||
|
|
||||||
|
// --- CARTÃO 1: SELEÇÃO DE MOEDAS ---
|
||||||
|
RoundedPanel cardMoedas = new RoundedPanel();
|
||||||
|
cardMoedas.setLayout(new BoxLayout(cardMoedas, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JLabel lblDe = new JLabel("Converter De:");
|
||||||
|
lblDe.setFont(new Font("Segoe UI", Font.PLAIN, 14));
|
||||||
|
lblDe.setForeground(Color.DARK_GRAY);
|
||||||
|
|
||||||
|
cmbFrom = new JComboBox<>(moedaDisplay);
|
||||||
|
styleComboBox(cmbFrom);
|
||||||
|
|
||||||
|
JLabel lblPara = new JLabel("Para:");
|
||||||
|
lblPara.setFont(new Font("Segoe UI", Font.PLAIN, 14));
|
||||||
|
lblPara.setForeground(Color.DARK_GRAY);
|
||||||
|
|
||||||
|
cmbTo = new JComboBox<>(moedaDisplay);
|
||||||
|
styleComboBox(cmbTo);
|
||||||
|
cmbTo.setSelectedIndex(2); // Padrão BRL
|
||||||
|
|
||||||
|
JPanel pnlDe = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlDe.setOpaque(false); pnlDe.add(lblDe);
|
||||||
|
JPanel pnlPara = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlPara.setOpaque(false); pnlPara.add(lblPara);
|
||||||
|
|
||||||
|
cardMoedas.add(pnlDe);
|
||||||
|
cardMoedas.add(cmbFrom);
|
||||||
|
cardMoedas.add(Box.createVerticalStrut(15));
|
||||||
|
cardMoedas.add(pnlPara);
|
||||||
|
cardMoedas.add(cmbTo);
|
||||||
|
|
||||||
|
mainPanel.add(cardMoedas);
|
||||||
|
mainPanel.add(Box.createVerticalStrut(15));
|
||||||
|
|
||||||
|
// --- CARTÃO 2: QUANTIDADE COM PLACEHOLDER ---
|
||||||
|
RoundedPanel cardValor = new RoundedPanel();
|
||||||
|
cardValor.setLayout(new BoxLayout(cardValor, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JLabel lblVal = new JLabel("Quantidade a Converter:");
|
||||||
|
lblVal.setFont(new Font("Segoe UI", Font.PLAIN, 14));
|
||||||
|
lblVal.setForeground(Color.DARK_GRAY);
|
||||||
|
JPanel pnlVal = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlVal.setOpaque(false); pnlVal.add(lblVal);
|
||||||
|
|
||||||
|
// Configuração do Placeholder
|
||||||
|
txtValue = new JTextField(PLACEHOLDER_TEXT);
|
||||||
|
txtValue.setForeground(Color.GRAY); // Cor de texto fantasma
|
||||||
|
styleTextField(txtValue);
|
||||||
|
|
||||||
|
// Evento para limpar o placeholder quando se clica
|
||||||
|
txtValue.addFocusListener(new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
if (txtValue.getText().equals(PLACEHOLDER_TEXT)) {
|
||||||
|
txtValue.setText("");
|
||||||
|
txtValue.setForeground(Color.BLACK); // Volta à cor normal para o user escrever
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost(FocusEvent e) {
|
||||||
|
if (txtValue.getText().isEmpty()) {
|
||||||
|
txtValue.setForeground(Color.GRAY);
|
||||||
|
txtValue.setText(PLACEHOLDER_TEXT); // Volta o texto fantasma se não escreverem nada
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cardValor.add(pnlVal);
|
||||||
|
cardValor.add(txtValue);
|
||||||
|
mainPanel.add(cardValor);
|
||||||
|
mainPanel.add(Box.createVerticalStrut(20));
|
||||||
|
|
||||||
|
// --- BOTÕES PRINCIPAIS ---
|
||||||
|
JButton btnConvert = new RoundedButton("Converter Agora", COLOR_BTN_PRIMARY, Color.BLACK);
|
||||||
|
mainPanel.add(btnConvert);
|
||||||
|
mainPanel.add(Box.createVerticalStrut(10));
|
||||||
|
|
||||||
|
JButton btnInvert = new RoundedButton("🔁 Inverter Moedas", COLOR_BTN_SECONDARY, Color.WHITE);
|
||||||
|
btnInvert.addActionListener(e -> inverterMoedas());
|
||||||
|
mainPanel.add(btnInvert);
|
||||||
|
mainPanel.add(Box.createVerticalStrut(20));
|
||||||
|
|
||||||
|
// --- CARTÃO 3: RESULTADO ---
|
||||||
|
RoundedPanel cardResult = new RoundedPanel();
|
||||||
|
cardResult.setLayout(new BoxLayout(cardResult, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JLabel lblRecebera = new JLabel("Você receberá:");
|
||||||
|
lblRecebera.setFont(new Font("Segoe UI", Font.PLAIN, 14));
|
||||||
|
lblRecebera.setForeground(Color.DARK_GRAY);
|
||||||
|
lblRecebera.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
|
lblResult = new JLabel("0.00", SwingConstants.CENTER);
|
||||||
|
lblResult.setFont(new Font("Segoe UI", Font.BOLD, 42));
|
||||||
|
lblResult.setForeground(new Color(20, 20, 20));
|
||||||
|
lblResult.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
|
lblResultSub = new JLabel("-");
|
||||||
|
lblResultSub.setFont(new Font("Segoe UI", Font.PLAIN, 16));
|
||||||
|
lblResultSub.setForeground(Color.DARK_GRAY);
|
||||||
|
lblResultSub.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
|
cardResult.add(Box.createVerticalStrut(10));
|
||||||
|
cardResult.add(lblRecebera);
|
||||||
|
cardResult.add(Box.createVerticalStrut(10));
|
||||||
|
cardResult.add(lblResult);
|
||||||
|
cardResult.add(lblResultSub);
|
||||||
|
cardResult.add(Box.createVerticalStrut(10));
|
||||||
|
|
||||||
|
mainPanel.add(cardResult);
|
||||||
|
|
||||||
|
// --- LÓGICA DO BOTÃO CONVERTER ---
|
||||||
|
btnConvert.addActionListener(e -> {
|
||||||
|
int indexFrom = cmbFrom.getSelectedIndex();
|
||||||
|
int indexTo = cmbTo.getSelectedIndex();
|
||||||
|
|
||||||
|
String input = txtValue.getText().replace(",", ".");
|
||||||
|
|
||||||
|
// Verifica se o utilizador não escreveu nada e deixou o placeholder lá
|
||||||
|
if (input.equals(PLACEHOLDER_TEXT) || input.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Insere um número válido, senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double val;
|
||||||
|
try {
|
||||||
|
val = Double.parseDouble(input);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Apenas números, por favor. Senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexFrom == indexTo) {
|
||||||
|
lblResult.setText(String.format("%.2f %s", val, moedaAbrev[indexTo]));
|
||||||
|
lblResultSub.setText(moedaDisplay[indexTo]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lblResult.setText("A calcular...");
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
String m1 = moedaAbrev[indexFrom];
|
||||||
|
String m2 = moedaAbrev[indexTo];
|
||||||
|
double rate = obterTaxaDeCambio(m1, m2);
|
||||||
|
double finalValue = val * rate;
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
lblResult.setText(String.format("%.2f %s", finalValue, m2));
|
||||||
|
lblResultSub.setText(moedaDisplay[indexTo]);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
lblResult.setText("Erro");
|
||||||
|
JOptionPane.showMessageDialog(this, "Erro de rede: " + ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Foca o ecrã para o placeholder funcionar logo na primeira vez
|
||||||
|
getContentPane().requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void inverterMoedas() {
|
||||||
|
int indexFrom = cmbFrom.getSelectedIndex();
|
||||||
|
int indexTo = cmbTo.getSelectedIndex();
|
||||||
|
cmbFrom.setSelectedIndex(indexTo);
|
||||||
|
cmbTo.setSelectedIndex(indexFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double obterTaxaDeCambio(String m1, String m2) throws Exception {
|
||||||
|
String urlStr = "https://economia.awesomeapi.com.br/json/last/" + m1 + "-" + m2;
|
||||||
|
URL url = new URL(urlStr);
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setConnectTimeout(5000);
|
||||||
|
conn.setReadTimeout(5000);
|
||||||
|
|
||||||
|
if (conn.getResponseCode() != 200) throw new IOException("HTTP Error: " + conn.getResponseCode());
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) response.append(line);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("\"bid\"\\s*:\\s*\"([^\"]+)\"");
|
||||||
|
Matcher matcher = pattern.matcher(response.toString());
|
||||||
|
if (matcher.find()) return Double.parseDouble(matcher.group(1));
|
||||||
|
else throw new Exception("Chave 'bid' não encontrada.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- CLASSES DE ESTILO CUSTOMIZADAS ---
|
||||||
|
|
||||||
|
// Painel Arredondado
|
||||||
|
class RoundedPanel extends JPanel {
|
||||||
|
public RoundedPanel() {
|
||||||
|
setOpaque(false);
|
||||||
|
setBorder(new EmptyBorder(15, 20, 15, 20));
|
||||||
|
setMaximumSize(new Dimension(360, 200));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g2.setColor(new Color(0, 0, 0, 20));
|
||||||
|
g2.fillRoundRect(2, 2, getWidth() - 4, getHeight() - 4, 25, 25);
|
||||||
|
g2.setColor(COLOR_CARD);
|
||||||
|
g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 4, 25, 25);
|
||||||
|
g2.dispose();
|
||||||
|
super.paintComponent(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Botão Arredondado
|
||||||
|
class RoundedButton extends JButton {
|
||||||
|
private Color bgColor;
|
||||||
|
public RoundedButton(String text, Color bg, Color fg) {
|
||||||
|
super(text);
|
||||||
|
this.bgColor = bg;
|
||||||
|
setForeground(fg);
|
||||||
|
setFont(new Font("Segoe UI", Font.BOLD, 18));
|
||||||
|
setFocusPainted(false);
|
||||||
|
setContentAreaFilled(false);
|
||||||
|
setBorderPainted(false);
|
||||||
|
setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
setMaximumSize(new Dimension(360, 50));
|
||||||
|
setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||||
|
|
||||||
|
addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseEntered(MouseEvent e) { bgColor = bg.brighter(); repaint(); }
|
||||||
|
public void mouseExited(MouseEvent e) { bgColor = bg; repaint(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g2.setColor(new Color(0, 0, 0, 30));
|
||||||
|
g2.fillRoundRect(2, 4, getWidth() - 4, getHeight() - 4, 20, 20);
|
||||||
|
g2.setColor(bgColor);
|
||||||
|
g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 5, 20, 20);
|
||||||
|
g2.dispose();
|
||||||
|
super.paintComponent(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleComboBox(JComboBox<String> cb) {
|
||||||
|
cb.setMaximumSize(new Dimension(320, 40));
|
||||||
|
cb.setFont(new Font("Segoe UI", Font.PLAIN, 16));
|
||||||
|
cb.setBackground(Color.WHITE);
|
||||||
|
cb.setFocusable(false);
|
||||||
|
cb.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void styleTextField(JTextField tf) {
|
||||||
|
tf.setMaximumSize(new Dimension(320, 45));
|
||||||
|
tf.setFont(new Font("Segoe UI", Font.PLAIN, 18));
|
||||||
|
tf.setBorder(BorderFactory.createCompoundBorder(
|
||||||
|
BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true),
|
||||||
|
new EmptyBorder(5, 10, 5, 10)
|
||||||
|
));
|
||||||
|
tf.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
new Main().setVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user