英文:
Linux, C, ncurses. Gnome terminal Ubuntu 22.6: printw printing twice in one instance
问题
在以下代码示例中,位于MouseLeftClicked函数中的ncurses printw打印了两次,而不是像预期的那样打印一次。我已经在互联网上搜索了类似的问题,但未能找到任何信息。我确信我错过了一些关于ncurses的基础知识,我现在正处于学习的初级阶段。非常感谢任何帮助。TIA
#include <stdbool.h>
#include <time.h>
#include <ncurses.h>
int main(void);
void MouseLeftClicked(int x, int y, char *caption);
int main(void)
{
int ch;
bool exit = false;
MEVENT event;
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
mousemask(ALL_MOUSE_EVENTS, NULL);
clear();
curs_set(0);
mvprintw(0, 0, "F1 exits");
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
attron(COLOR_PAIR(1));
mvprintw(10, 1, " Exit ");
attroff(COLOR_PAIR(1));
refresh();
do
{
ch = getch();
if(ch == KEY_MOUSE)
{
mvprintw(2, 0, "Got KEY_MOUSE");
if(getmouse(&event) == OK)
{
mvprintw(3, 0, "Got mouse event");
if(event.bstate & BUTTON1_CLICKED)
{
mvprintw(4, 0, "Got click on button #1");
mvprintw(5, 0, "Mouse position: x=%d y=%d ", event.x, event.y);
refresh();
if(event.x > 0 && event.x < 7 && event.y == 10)
MouseLeftClicked(event.x+1, event.y+1, " Exit ");
ch = 0;
}
}
}
if(ch == KEY_F(1))
exit = true;
} while(! exit);
curs_set(1);
endwin();
return 0;
}
void MouseLeftClicked(int x, int y, char *caption)
{
struct timespec tim, tim2;
tim.tv_sec = 0;
tim.tv_nsec = 999999998L;
init_pair(1, COLOR_WHITE, COLOR_GREEN);
attron(COLOR_PAIR(1));
mvprintw(y, x, "%s", caption);
//printw("%s", caption);
attroff(COLOR_PAIR(1));
refresh();
//nanosleep(&tim, &tim2);
//init_pair(1, COLOR_WHITE, COLOR_BLUE);
//attron(COLOR_PAIR(1));
//mvprintw(y, x, " Exit ");
//attroff(COLOR_PAIR(1));
}
英文:
In the code example below, the ncurses printw located in the MouseLeftClicked function is printing twice instead of once as intended. I've scoured the Internet looking for a similar issue but have been unable to find anything. I'm sure I'm missing something fundamental to ncurses, which I'm in the beginning stages of learning. Any help is greatly appreciated. TIA
#include <stdbool.h>
#include <time.h>
#include <ncurses.h>
int main(void);
void MouseLeftClicked(int x, int y, char *caption);
int main(void)
{
int ch;
bool exit = false;
MEVENT event;
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
mousemask(ALL_MOUSE_EVENTS, NULL);
clear();
curs_set(0);
mvprintw(0, 0, "F1 exits");
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
attron(COLOR_PAIR(1));
mvprintw(10, 1, " Exit ");
attroff(COLOR_PAIR(1));
refresh();
do
{
ch = getch();
if(ch == KEY_MOUSE)
{
mvprintw(2, 0, "Got KEY_MOUSE");
if(getmouse(&event) == OK)
{
mvprintw(3, 0, "Got mouse event");
if(event.bstate & BUTTON1_CLICKED)
{
mvprintw(4, 0, "Got click on button #1");
mvprintw(5, 0, "Mouse position: x=%d y=%d ", event.x, event.y);
refresh();
if(event.x > 0 && event.x < 7 && event.y == 10)
MouseLeftClicked(event.x+1, event.y+1, " Exit ");
ch = 0;
}
}
}
if(ch == KEY_F(1))
exit = true;
} while(! exit);
curs_set(1);
endwin();
return 0;
}
void MouseLeftClicked(int x, int y, char *caption)
{
struct timespec tim, tim2;
tim.tv_sec = 0;
tim.tv_nsec = 999999998L;
init_pair(1, COLOR_WHITE, COLOR_GREEN);
attron(COLOR_PAIR(1));
mvprintw(y, x, "%s", caption);
//printw("%s", caption);
attroff(COLOR_PAIR(1));
refresh();
//nanosleep(&tim, &tim2);
//init_pair(1, COLOR_WHITE, COLOR_BLUE);
//attron(COLOR_PAIR(1));
//mvprintw(y, x, " Exit ");
//attroff(COLOR_PAIR(1));
}
答案1
得分: 3
mvprintw
在该函数中并不会打印两次。实际上,它确切地在您指定的位置打印文本。之所以不在原始的“Exit”文本位置打印是因为您提供了坐标event.x+1, event.y+1
。
之所以两者都以绿色绘制是因为您用不同的颜色替换了颜色对1,然后调用了refresh()
。原始的“Exit”文本使用了该属性,所以结果是它被重新着色。
如果您只想改变按钮的颜色,您不需要使用mvprintw
再次绘制文本。只需更改颜色对并刷新:
init_pair(1, COLOR_WHITE, COLOR_GREEN);
refresh();
进一步阅读:init_pair文档
我强烈建议您使用枚举值或类似的方式为颜色对命名,而不是硬编码魔术数字。这将使代码更可读,减少错误。
示例:
enum ColorPairs {
kColorPairDefault = 0, // 特殊默认颜色对
kColorPairButton, // 我们按钮的颜色
};
然后,初始设置如下所示:
start_color();
init_pair(kColorPairButton, COLOR_WHITE, COLOR_BLUE);
attron(COLOR_PAIR(kColorPairButton));
mvprintw(10, 1, " Exit ");
attroff(COLOR_PAIR(kColorPairButton));
refresh();
更新如下所示:
init_pair(kColorPairButton, COLOR_WHITE, COLOR_GREEN);
refresh();
英文:
The mvprintw
is not printing twice in that function. It is in fact printing text exactly where you told it to. That happens to not be in the same location as the original Exit
text because you provided the co-ordinate event.x+1, event.y+1
.
The reason why both are drawn in green is because you replaced color pair 1 with a different color and then called refresh()
. The original Exit
text uses that attribute, so the result is that it's re-colored.
If all you want to do is change the button color, you do not need to draw the text again with mvprintw
. Just change the color pair and refresh:
init_pair(1, COLOR_WHITE, COLOR_GREEN);
refresh();
Further reading: init_pair documentation
I would highly recommend you use enum values or similar to name your color pairs, instead of hard-coding magic numbers. That will make the code more readable and less error-prone.
Example:
enum ColorPairs {
kColorPairDefault = 0, // special default color pair
kColorPairButton, // color of our button
};
Then, the initial setup looks like this:
start_color();
init_pair(kColorPairButton, COLOR_WHITE, COLOR_BLUE);
attron(COLOR_PAIR(kColorPairButton));
mvprintw(10, 1, " Exit ");
attroff(COLOR_PAIR(kColorPairButton));
refresh();
And the update looks like this:
init_pair(kColorPairButton, COLOR_WHITE, COLOR_GREEN);
refresh();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论