You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino/C++创建对象时能否重写方法?OLED GUI按钮实现咨询

Great question! Since you're coming from Java, you're probably used to anonymous classes as a clean way to define one-off callback behaviors—and while C++ doesn't have exact equivalents, there are several idioms that let you achieve the same goal for your Arduino OLED GUI buttons. Let's walk through the most practical approaches tailored to your use case:

1. Lambda Expressions with std::function (Closest to Java Anonymous Classes)

This is the most direct analog to Java's anonymous classes. C++11 (and later, which Arduino IDE supports by default) introduces lambdas—inline, anonymous functions that can capture variables from the surrounding scope, just like Java anonymous classes accessing outer variables.

Combine lambdas with std::function to create flexible callback handlers for your buttons:

#include <Arduino.h>
#include <U8g2lib.h>
#include <functional> // Required for std::function

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

class Button {
private:
  int x, y, width, height;
  String label;
  std::function<void()> onClickCallback;

public:
  Button(int btnX, int btnY, int btnW, int btnH, String btnLabel, std::function<void()> callback)
    : x(btnX), y(btnY), width(btnW), height(btnH), label(btnLabel), onClickCallback(callback) {}

  // Check if the button was clicked (simplified; replace with actual input logic)
  void handleClick(int touchX, int touchY) {
    if (touchX >= x && touchX <= x + width && touchY >= y && touchY <= y + height) {
      if (onClickCallback) onClickCallback();
    }
  }

  // Draw the button to the OLED
  void draw() {
    u8g2.drawFrame(x, y, width, height);
    u8g2.setCursor(x + 5, y + 15);
    u8g2.print(label);
  }
};

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  pinMode(LED_BUILTIN, OUTPUT);

  // Create buttons with lambda callbacks (just like Java anonymous classes!)
  Button ledOnBtn(10, 10, 50, 20, "LED ON", [](){
    digitalWrite(LED_BUILTIN, HIGH);
    // Add your custom on-click logic here
  });

  Button ledOffBtn(10, 40, 50, 20, "LED OFF", [](){
    digitalWrite(LED_BUILTIN, LOW);
    // More custom logic here
  });

  // In a real project, store buttons in a vector/array to loop through them
  // std::vector<Button> buttons = {ledOnBtn, ledOffBtn};
}

void loop() {
  u8g2.clearBuffer();
  
  // Draw all buttons
  // for(auto& btn : buttons) btn.draw();

  // Simulate touch input (replace with actual hardware input reading)
  // int touchX = ...; int touchY = ...;
  // for(auto& btn : buttons) btn.handleClick(touchX, touchY);

  u8g2.sendBuffer();
  delay(100);
}

You can even capture local variables using [&] (by reference) or [=] (by value) in the lambda, just like how Java anonymous classes access outer scope variables.

2. Function Pointers (Simple for Basic Callbacks)

If you don't need to capture variables, function pointers are a lightweight alternative. They work well for straightforward, stateless callbacks:

// Define a callback function type
typedef void (*ButtonCallback)();

class Button {
private:
  int x, y, width, height;
  String label;
  ButtonCallback onClick;

public:
  Button(int btnX, int btnY, int btnW, int btnH, String btnLabel, ButtonCallback callback)
    : x(btnX), y(btnY), width(btnW), height(btnH), label(btnLabel), onClick(callback) {}

  void handleClick(int touchX, int touchY) {
    if (touchX >= x && touchX <= x + width && touchY >= y && touchY <= y + height) {
      if (onClick) onClick();
    }
  }

  void draw() {
    u8g2.drawFrame(x, y, width, height);
    u8g2.setCursor(x + 5, y + 15);
    u8g2.print(label);
  }
};

// Define your callback functions
void turnLedOn() {
  digitalWrite(LED_BUILTIN, HIGH);
}

void turnLedOff() {
  digitalWrite(LED_BUILTIN, LOW);
}

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  pinMode(LED_BUILTIN, OUTPUT);

  Button ledOnBtn(10, 10, 50, 20, "LED ON", turnLedOn);
  Button ledOffBtn(10, 40, 50, 20, "LED OFF", turnLedOff);
}

3. Abstract Base Classes + Concrete Subclasses (For Complex Logic)

For more complex callback behaviors (with state or multiple methods), you can use an abstract base class with pure virtual functions, then create concrete subclasses for each button's action—this is the closest to Java's explicit subclassing pattern:

// Abstract base class for button actions
class ButtonAction {
public:
  virtual void onClick() = 0; // Pure virtual function (must be overridden)
};

class Button {
private:
  int x, y, width, height;
  String label;
  ButtonAction* action;

public:
  Button(int btnX, int btnY, int btnW, int btnH, String btnLabel, ButtonAction* btnAction)
    : x(btnX), y(btnY), width(btnW), height(btnH), label(btnLabel), action(btnAction) {}

  void handleClick(int touchX, int touchY) {
    if (touchX >= x && touchX <= x + width && touchY >= y && touchY <= y + height) {
      if (action) action->onClick();
    }
  }

  void draw() {
    u8g2.drawFrame(x, y, width, height);
    u8g2.setCursor(x + 5, y + 15);
    u8g2.print(label);
  }
};

// Concrete subclass for turning the LED on
class LedOnAction : public ButtonAction {
public:
  void onClick() override {
    digitalWrite(LED_BUILTIN, HIGH);
    // Add complex logic here if needed
  }
};

// Concrete subclass for turning the LED off
class LedOffAction : public ButtonAction {
public:
  void onClick() override {
    digitalWrite(LED_BUILTIN, LOW);
    // More complex logic here
  }
};

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  pinMode(LED_BUILTIN, OUTPUT);

  LedOnAction ledOn;
  LedOffAction ledOff;

  Button ledOnBtn(10, 10, 50, 20, "LED ON", &ledOn);
  Button ledOffBtn(10, 40, 50, 20, "LED OFF", &ledOff);
}

Final Recommendation

For your Arduino GUI project, the lambda + std::function approach is the best choice—it's concise, flexible, and mirrors the convenience of Java's anonymous classes perfectly. It lets you define one-off callback logic inline without cluttering your code with extra classes or functions.

内容的提问来源于stack exchange,提问作者AirToTec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:39:05