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