qml 구현 채 팅 인터페이스
102682 단어 QT 프로 그래 밍
자신 이 필요 로 하 는 기능 을 추 가 했 습 니 다. listview 의 delegate 문 자 는 마우스 로 선택 하고 복사 할 수 있 으 며 키보드 ctrl + c 복사, item 의 삭 제 를 받 을 수 있 습 니 다. 마우스 가 맨 위로 미 끄 러 질 때 더 많은 item 을 불 러 오고 상호작용 채 팅 방식 을 지양 하 며 푸 시 에 만 사용 할 수 있 습 니 다. 상기 링크 를 참고 하 는 것 을 권장 합 니 다.
직접 코드 붙 이기:
import QtQuick 2.6
import QtQuick.Layouts 1.3 import QtQuick.Controls 2.0 Rectangle { id: root color: "#f5f5f5" function add_message(timetext,issame,text,who,istip,type,id) { if(text.length <= 0) { return; } listView.model.insert(0, {"content": text, "send": who,"msgTime":timetext,"same":issame,"tip":istip, "send_type": type,"id": id}); //verScrollBar.increase() // verScrollBar.setPosition(1.0) } function add_more_message(timetext,issame,text,who,istip,type,id) { if(text.length <= 0) { return; } var count=listView.model.count listView.model.insert(count, {"content": text, "send": who,"msgTime":timetext,"same":issame,"tip":istip, "send_type": type,"id": id}); //verScrollBar.increase() //verScrollBar.setPosition(1.0) } function clearListview() { listView.model.clear() } function re_edit_item(index) { var count=listView.model.count if(count>0){ listView.model.remove(index,1) } } property bool showtip: false function show_tip() { showtip=true } function hide_tip() { showtip=false } ColumnLayout { id:page anchors.fill: parent // focus true focus: true // messageText , //page ctrl+c messagetext copy signal ctrl_c() Keys.onPressed: { if((event.modifiers===Qt.ControlModifier) && (event.key===Qt.Key_C)){ // page.ctrl_c() } event.accepted=true } Rectangle { id:tiprect width: tiptext.implicitWidth+10 height: 30 color: "#f5f5f5" anchors.horizontalCenter: parent.horizontalCenter visible:showtip Label { id: tiptext text: " " verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: "#1f61ff" font.family: " " font.pointSize: 9 anchors.fill: parent anchors.margins:0 } } ListView { id: listView Layout.fillWidth: true Layout.fillHeight: true Layout.margins:14 Layout.rightMargin: 0 displayMarginBeginning: 40 displayMarginEnd: 40 verticalLayoutDirection: ListView.BottomToTop spacing:14 model:ListModel{} delegate: Column { anchors.left: parent.left spacing: 14 width: parent.width property bool sendmessage: send property bool sameTime: same // Rectangle { width: timetext.implicitWidth+10 height: timetext.implicitHeight+2 color: tip ? "lightgrey" : "#d1cece" anchors.horizontalCenter: parent.horizontalCenter visible: !same Label { id: timetext text: msgTime verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: tip ? "red" : "white" font.family: " " font.pointSize: 9 anchors.fill: parent anchors.margins:0 } } // Row { id: messageRow spacing: 6 anchors.left: parent.left visible: !tip // Image { id: avatarLeft height: 36 width: height source: "qrc:/image/touxiang.jpg" } // Rectangle { width: Math.min(messageText.implicitWidth +14, listView.width -98) height: messageText.implicitHeight + 16 color: send ? "#9dea6a" : "#eeeeee" radius: 3 TextEdit { id: messageText text: content font.family: " " //color: "#9dea6a" font.pointSize: 11 anchors.fill: parent anchors.topMargin: 9 anchors.bottomMargin: 7 anchors.rightMargin: 7 anchors.leftMargin: 7 wrapMode: TextEdit.Wrap enabled: true readOnly: true selectByKeyboard: true selectByMouse: true selectedTextColor: "white" persistentSelection:true selectionColor: "#3396FF" // listview Drag.active: text_area.drag.active } // , MouseArea{ id:text_area width: parent.width height: parent.height acceptedButtons: Qt.LeftButton|Qt.RightButton // , , drag.target: messageText hoverEnabled: true property int _startpos: 0 property int _endpos: 0 property bool canselect: false onClicked: { // = ,js if(mouse.button===Qt.RightButton){ // , if(_startpos<_endpos){ messageText.select(_startpos-1,_endpos) } else { if(_startpos>_endpos){ messageText.select(_endpos-1,_startpos) } else { messageText.select(_startpos,_endpos) } } // mainwindow mainwindow.listview_item_clicked(index,id,send_type,messageText.selectedText,messageText.text) } } onEntered: { // , page.ctrl_c.connect(message_cpoy) } // function message_cpoy(){ messageText.copy() } // , , onExited: { messageText.deselect() _startpos=0 _endpos=0 page.ctrl_c.disconnect(message_cpoy) } // onMouseXChanged: { if(canselect){ _endpos=messageText.positionAt(mouseX,mouseY) // 1, if(_startpos<_endpos){ messageText.select(_startpos-1,_endpos) } else { if(_startpos>_endpos){ messageText.select(_endpos-1,_startpos) } else { messageText.select(_startpos,_endpos) } } } } // onPressed: { if(mouse.button===Qt.LeftButton){ canselect=true _startpos=messageText.positionAt(mouseX,mouseY) } } // onReleased: { if(mouse.button===Qt.LeftButton){ //messageText.copy() canselect=false } } } } } } ScrollBar.vertical: ScrollBar { id: verScrollBar } // onContentYChanged: { //console.log("contenty:"+contentY) //console.log("originy"+originY) var x=contentY-originY if(x==0){ mainwindow.load_more_for_chatwidget(); } } } /* cpp Connections{ target: mywindows onShowmymsg:add_message(arg_1,arg_2,arg_3,arg_4,arg_5) }*/ } } / / cpp 의 함수: (cpp 에서 상하 문 속성 을 설정 한 후 사용 가능)
/ / quickwidget qml 불 러 오기
QUrl source("qrc:/myqml/1.qml"); // c++ qml, qml c++ Q_INVOKABLE public public ui->quickWidget->rootContext()->setContextProperty("mainwindow",this); // //qmlRegisterType("io.qt.mainwindow", 1, 0, "Mwindow"); ui->quickWidget->setSource(source); / / 하나 추가
QQuickItem *item=ui->quickWidget->rootObject();
QVariant returnVar;QString send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss").toString("hh:mm");QVariant arg1 = send_time1;QVariant arg2;QVariant arg3 =send_text;QVariant arg4 =true;QVariant arg5 =false;QVariant arg6="no_reedit";QVariant arg7=-1;if(send_time1==lastSend_time){arg2= true;}else{arg2=false;lastSend_time=send_time1;}QMetaObject::invokeMethod(item, "add_message",Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1),Q_ARG(QVariant, arg2),Q_ARG(QVariant, arg3),Q_ARG(QVariant, arg4),Q_ARG(QVariant, arg5),Q_ARG(QVariant, arg6),Q_ARG(QVariant, arg7));
/ / cpp 의 함수
void mainwindow::listview_item_clicked(const int index, const int id, const QString sendtype,const QString selectedtext,const QString itemtext){qml_id=id;qml_index=index;qml_sendtype=sendtype;qml_selected_text=selectedtext;qml_item_text=itemtext;//qDebug()<//qDebug()<ui->quickWidget->customContextMenuRequested(QPoint(0,0));}
qml 의 값 을 개인 변수 에 부여 하면 복사 및 방향 취소 기능 을 실현 할 수 있 습 니 다.
//취소QQuickItem *item=ui->quickWidget->rootObject();QVariant returnVar;QVariant arg1 = qml_item_index;QMetaObject::invokeMethod(item, "re_edit_item",Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1));label_who *label_w1 = (label_who *)(ui->label_2->userData(Qt::UserRole));//QString send_type=label_w1->send_type;QString send_who=label_w1->send_who;
/ / 선택 한 텍스트 를 복사 합 니 다. qml 파일 에서 선택 한 후 ctrl + c 를 누 르 면 직접 복사 할 수 있 습 니 다.
void mainwindow::copy_content(){QClipboard *clipboard=QApplication::clipboard();clipboard->setText(qml_selected_text,QClipboard::Clipboard);}
void mainwindow::load_more_for_chatwidget(){if(last_query_number<5){ // 5QQuickItem *item=ui->quickWidget->rootObject();QString current_to_usr_name=ui->listWidget->currentItem()->data(Qt::UserRole+1).toString();QString item_type=ui->listWidget->currentItem()->data(Qt::UserRole).toString();QString item_mail=ui->listWidget->currentItem()->data(Qt::UserRole+2).toString();//QSqlQuery sql_query;QString select_his_content;if(item_type=="user"){int last_number=last_query_number*10;//limit ...select_his_content="select send_time,send_text from his_tousr ""where tousrmail=:mail ""order by send_time desc ""limit 10 offset :last_number";sql_query.prepare(select_his_content);sql_query.bindValue(":mail",item_mail);sql_query.bindValue(":last_number",last_number);}else{if(item_type=="group"){int last_number=last_query_number*10;select_his_content="select send_time,send_text from his_group ""where usrgroupname=:groupname ""order by send_time desc ""limit 10 offset :last_number";sql_query.prepare(select_his_content);sql_query.bindValue(":groupname",current_to_usr_name);sql_query.bindValue(":last_number",last_number);}}if(sql_query.exec()){while(sql_query.next()){QString send_time=sql_query.value(0).toString();QString his_content=sql_query.value(1).toString();// ,QString yestoday_date=QDateTime::currentDateTime().addDays(-1).toString("yyyyMMdd");QString today_date=QDateTime::currentDateTime().toString("yyyyMMdd");if(send_time.left(8)==today_date){send_time=(send_time.mid(8,2)+":"+send_time.mid(10,2));}else {if(send_time.left(8)==yestoday_date){send_time=" "+send_time.mid(8,2)+":"+send_time.mid(10,2);}else{if(send_time.left(4)==today_date.left(4)){QDateTime send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss");send_time=send_time1.toString("M dd hh:mm");}else{QDateTime send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss");send_time=send_time1.toString("yyyy M dd hh:mm");}}}QVariant returnVar;QVariant arg1 = send_time;QVariant arg2;QVariant arg3 =his_content;QVariant arg4 =true;QVariant arg5 =false;QVariant arg6="no_reedit";QVariant arg7=-1;if(send_time==lastSend_time){arg2= true;}else{arg2=false;lastSend_time=send_time;}QMetaObject::invokeMethod(item, "add_more_message",Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1),Q_ARG(QVariant, arg2),Q_ARG(QVariant, arg3),Q_ARG(QVariant, arg4),Q_ARG(QVariant, arg5),Q_ARG(QVariant, arg6),Q_ARG(QVariant, arg7));ui->quickWidget->repaint();}last_query_number++;}else{qDebug()<<sql_query.lastError();}} else {qDebug()<<"nidaye";QQuickItem *item=ui->quickWidget->rootObject();QMetaObject::invokeMethod(item,"show_tip");}}
/ / 기록 해 주세요.